todas las clases funcionales

This commit is contained in:
2024-05-16 16:13:59 +02:00
parent 0c1ef39a32
commit 5f4dc6fc01
6 changed files with 119 additions and 75 deletions

View File

@ -1,8 +1,11 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.flutter_project">
<application
android:label="flutter_project"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
@ -11,34 +14,32 @@
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<!-- Especifica un tema de Android para aplicar a esta actividad tan pronto como se haya iniciado el proceso de Android. Este tema es visible para el usuario mientras la interfaz de usuario de Flutter se inicializa. Después de eso, este tema continúa determinando el fondo de la ventana detrás de la interfaz de usuario de Flutter. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" />
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<!-- No elimines los metadatos a continuación. Esto es utilizado por la herramienta Flutter para generar GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility?hl=en and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
</application>
<!-- Requerido para consultar actividades que pueden procesar texto, ver: https://developer.android.com/training/package-visibility?hl=en y https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT. En particular, esto es utilizado por el motor Flutter en io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
<!-- Permiso de Internet -->
<uses-permission android:name="android.permission.INTERNET" />
</manifest>

View File

@ -41,11 +41,13 @@ Future<void> launchAemetURL() async {
final url = Uri.parse(urlString);
try {
if (await canLaunch(urlString)) {
await launch(urlString);
/* if (await canLaunch(urlString)) {
await launch(urlString);
} else {
throw 'Could not launch $urlString';
}
}*/
} catch (e) {
throw Exception('Error al lanzar la URL de Aemet: $e');
}

View File

@ -93,7 +93,7 @@ List<Map<String, dynamic>> embalsesData = [];
// Fondo con la imagen
Positioned.fill(
child: Image(
image: AssetImage('assets/logo-fondo.png'),
image: AssetImage('assets/logo-fondo-verde.png'),
fit: BoxFit.cover,
),
),
@ -123,6 +123,7 @@ List<Map<String, dynamic>> embalsesData = [];
child: Text(
nombreEmbalse!,
style: TextStyle(
fontSize : 25.0,
fontWeight: FontWeight.bold,
),
),
@ -142,7 +143,7 @@ List<Map<String, dynamic>> embalsesData = [];
(index) => Text(
'${descripciones[index]}: ${listaElementos[index]}',
style: TextStyle(
fontWeight: FontWeight.normal,
fontWeight: FontWeight.normal, fontSize : 20.0
),
),
),

View File

@ -35,7 +35,7 @@ class MyHomePage extends StatelessWidget {
MaterialPageRoute(builder: (context) => const NoticiasPage()),
);},
child: SizedBox(
width: 250.0,
width: 300.0,
child: Padding(
padding: const EdgeInsets.only(bottom: 20.0),
child: Container(
@ -49,7 +49,7 @@ class MyHomePage extends StatelessWidget {
textAlign: TextAlign.center,
style: TextStyle(
color: Color.fromARGB(255, 255, 255, 255),
fontSize: 27.0,
fontSize: 32.0,
fontWeight: FontWeight.bold,
),
),
@ -65,7 +65,7 @@ class MyHomePage extends StatelessWidget {
);
},
child: SizedBox(
width: 250.0,
width: 300.0,
child: Padding(
padding: const EdgeInsets.only(bottom: 20.0),
child: Container(
@ -79,7 +79,7 @@ class MyHomePage extends StatelessWidget {
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 27.0,
fontSize: 32.0,
fontWeight: FontWeight.bold,
),
),
@ -95,7 +95,7 @@ class MyHomePage extends StatelessWidget {
);
},
child: SizedBox(
width: 250.0,
width: 300.0,
child: Padding(
padding: const EdgeInsets.only(bottom: 20.0),
child: Container(
@ -109,7 +109,7 @@ class MyHomePage extends StatelessWidget {
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 27.0,
fontSize: 32.0,
fontWeight: FontWeight.bold,
),
),
@ -122,7 +122,7 @@ class MyHomePage extends StatelessWidget {
launchAemetURL();
},
child: SizedBox(
width: 250.0,
width: 300.0,
child: Padding(
padding: const EdgeInsets.only(bottom: 20.0),
child: Container(
@ -136,7 +136,7 @@ class MyHomePage extends StatelessWidget {
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 27.0,
fontSize: 32.0,
fontWeight: FontWeight.bold,
),
),

View File

@ -12,7 +12,7 @@ class NoticiasPage extends StatefulWidget {
}
class _NoticiasPageState extends State<NoticiasPage> {
Map<String, List<String>> noticiasPorTitulo = {};
Map<String, List<Future<String>>> noticiasPorTitulo = {};
@override
void initState() {
@ -24,47 +24,71 @@ class _NoticiasPageState extends State<NoticiasPage> {
final response = await http.get(Uri.parse('http://www.crcivan.com/escaparate/noticias.cgi?idpadre=92776&idempresa=31637'));
if (response.statusCode == 200) {
var document = htmlParser.parse(response.body);
var dataElements = document.querySelectorAll('html > body > div > center > table > tbody > tr > td > div > center > table > tbody > tr > td > table > tbody > tr > td > font');
var tituloElements = document.querySelectorAll('html > body > div > center > table > tbody > tr > td > div > center > table > tbody > tr > td > table > tbody > tr > td > b > a');
for (int i = 0; i < tituloElements.length; i++) {
String titulo = tituloElements[i].text.trim();
String noticia = dataElements[i].text.trim();
// Extrayendo el enlace href del elemento <a>
var linkElement = tituloElements[i];
String? link = linkElement.attributes['href'];
if (!noticiasPorTitulo.containsKey(titulo)) {
noticiasPorTitulo[titulo] = [];
if (link != null) {
noticiasPorTitulo[titulo] = [cargarContenidoUrl(link)];
}
noticiasPorTitulo[titulo]?.add(noticia);
}
// Esperar todas las promesas para que se resuelvan
await Future.wait(noticiasPorTitulo.values.expand((element) => element).toList());
setState(() {});
} else {
throw Exception('fallo al cargar noticias');
throw Exception('Fallo al cargar noticias');
}
}
//Función para desplegar noticias desde los contenedores
/*Future<void> obtenerDatosNoticias() async {
var linkElements = document.querySelectorAll('html > body > div > center > table > tbody > tr > td > div > center > table > tbody > tr > td > table > tbody > tr > td > a');
String? link = linkElements[i].attributes['href'];
if (response.statusCode == 200) {
for (int i = 0; i < tituloElements.length; i++) {
String titulo = tituloElements[i].text.trim();
String noticia = dataElements[i].text.trim();
Future<String> cargarContenidoUrl(String url) async {
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
var document = htmlParser.parse(response.body);
var paragraphAndLists = document.querySelectorAll('html > body > div > center > table > tbody > tr > td > div > center > table > tbody > tr > td > table > tbody > tr > td > font > font > p, html > body > div > center > table > tbody > tr > td > div > center > table > tbody > tr > td > table > tbody > tr > td > font > font > ul');
String content = '';
String currentParagraphContent = '';
if (!noticiasPorTitulo.containsKey(titulo)) {
noticiasPorTitulo[titulo] = [];
for (var element in paragraphAndLists) {
if (element.localName == 'p') {
// Guardar el contenido del párrafo actual
if (currentParagraphContent.isNotEmpty) {
content += currentParagraphContent + '\n';
currentParagraphContent = '';
}
currentParagraphContent += element.text.trim() + '\n';
} else if (element.localName == 'ul') {
// Si hay un párrafo antes de la lista, agregarlo al contenido
if (currentParagraphContent.isNotEmpty) {
content += currentParagraphContent + '\n';
currentParagraphContent = '';
}
// Agregar la lista al contenido
var listItems = element.querySelectorAll('li');
for (var listItem in listItems) {
content += '- ${listItem.text.trim()}\n';
}
noticiasPorTitulo[titulo]?.add(noticia);
}
setState(() {});
} else {
throw Exception('fallo al cargar noticias');
}
}*/
// Agregar el último párrafo si no hay lista después
if (currentParagraphContent.isNotEmpty) {
content += currentParagraphContent + '\n';
}
return content;
} else {
throw Exception('Fallo al cargar contenido de URL: $url');
}
}
@override
Widget build(BuildContext context) {
@ -74,7 +98,7 @@ class _NoticiasPageState extends State<NoticiasPage> {
children: [
Positioned.fill(
child: Image(
image: AssetImage('assets/logo-fondo.png'),
image: AssetImage('assets/logo-fondo-verde.png'),
fit: BoxFit.cover,
),
),
@ -82,24 +106,40 @@ class _NoticiasPageState extends State<NoticiasPage> {
itemCount: noticiasPorTitulo.length,
itemBuilder: (context, index) {
String titulo = noticiasPorTitulo.keys.elementAt(index);
List<String>? noticias = noticiasPorTitulo[titulo];
List<Future<String>>? noticias = noticiasPorTitulo[titulo];
return ExpansionTile(
title: Text(
titulo,
style: TextStyle(fontWeight: FontWeight.bold),
),
children: noticias != null
? noticias.map((noticia) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
noticia,
style: TextStyle(fontSize: 16.0),
),
);
}).toList()
: [],
return FutureBuilder<List<String>>(
future: Future.wait(noticias ?? []),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else if (!snapshot.hasData) {
return Text('No hay datos');
} else {
return Container(
color: Colors.white.withOpacity(0.5), // Fondo blanco con 50% de opacidad
margin: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8.0),
child: ExpansionTile(
title: Text(
titulo,
style: TextStyle(fontWeight: FontWeight.bold),
),
children: snapshot.data!.map((noticia) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
noticia,
style: TextStyle(fontSize: 16.0),
),
);
}).toList(),
),
);
}
},
);
},
),

View File

@ -64,7 +64,7 @@ Widget build(BuildContext context) {
// Fondo con la imagen
Positioned.fill(
child: Image(
image: AssetImage('assets/logo-fondo.png'),
image: AssetImage('assets/logo-fondo-verde.png'),
fit: BoxFit.cover,
),
),
@ -80,7 +80,7 @@ Widget build(BuildContext context) {
if (hasMes)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0), // Add padding to the divider
child: Divider(color: Colors.blue, thickness: 3.0), // Divider antes del párrafo
child: Divider(color: Colors.green, thickness: 3.0), // Divider antes del párrafo
),
hasText
? ListTile(
@ -89,7 +89,7 @@ Widget build(BuildContext context) {
datos[index],
textAlign: TextAlign.center,
style: TextStyle(
color: hasMes ? Color.fromARGB(255, 0, 0, 0) : Color.fromARGB(255, 0, 0, 0), fontWeight : FontWeight.bold
color: hasMes ? Color.fromARGB(255, 0, 0, 0) : Color.fromARGB(255, 0, 0, 0), fontWeight : FontWeight.bold, fontSize : 22.0
),
),
),
@ -98,7 +98,7 @@ Widget build(BuildContext context) {
if (hasMes)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 100.0), // Add padding to the divider
child: Divider(color: Colors.blue, thickness: 1.0), // Divider después del párrafo
child: Divider(color: Colors.green, thickness: 1.0), // Divider después del párrafo
),
],
);