todas las clases funcionales
This commit is contained in:
@ -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
|
<application
|
||||||
android:label="flutter_project"
|
android:label="flutter_project"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
android:icon="@mipmap/ic_launcher">
|
android:icon="@mipmap/ic_launcher">
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
@ -11,34 +14,32 @@
|
|||||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
android:windowSoftInputMode="adjustResize">
|
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>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
</intent-filter>
|
</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>
|
</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
|
<meta-data
|
||||||
android:name="flutterEmbedding"
|
android:name="flutterEmbedding"
|
||||||
android:value="2" />
|
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>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
||||||
<data android:mimeType="text/plain"/>
|
<data android:mimeType="text/plain"/>
|
||||||
</intent>
|
</intent>
|
||||||
</queries>
|
</queries>
|
||||||
|
|
||||||
|
<!-- Permiso de Internet -->
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@ -41,11 +41,13 @@ Future<void> launchAemetURL() async {
|
|||||||
final url = Uri.parse(urlString);
|
final url = Uri.parse(urlString);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (await canLaunch(urlString)) {
|
await launch(urlString);
|
||||||
|
|
||||||
|
/* if (await canLaunch(urlString)) {
|
||||||
await launch(urlString);
|
await launch(urlString);
|
||||||
} else {
|
} else {
|
||||||
throw 'Could not launch $urlString';
|
throw 'Could not launch $urlString';
|
||||||
}
|
}*/
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw Exception('Error al lanzar la URL de Aemet: $e');
|
throw Exception('Error al lanzar la URL de Aemet: $e');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -93,7 +93,7 @@ List<Map<String, dynamic>> embalsesData = [];
|
|||||||
// Fondo con la imagen
|
// Fondo con la imagen
|
||||||
Positioned.fill(
|
Positioned.fill(
|
||||||
child: Image(
|
child: Image(
|
||||||
image: AssetImage('assets/logo-fondo.png'),
|
image: AssetImage('assets/logo-fondo-verde.png'),
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -123,6 +123,7 @@ List<Map<String, dynamic>> embalsesData = [];
|
|||||||
child: Text(
|
child: Text(
|
||||||
nombreEmbalse!,
|
nombreEmbalse!,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
fontSize : 25.0,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -142,7 +143,7 @@ List<Map<String, dynamic>> embalsesData = [];
|
|||||||
(index) => Text(
|
(index) => Text(
|
||||||
'${descripciones[index]}: ${listaElementos[index]}',
|
'${descripciones[index]}: ${listaElementos[index]}',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.normal,
|
fontWeight: FontWeight.normal, fontSize : 20.0
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -35,7 +35,7 @@ class MyHomePage extends StatelessWidget {
|
|||||||
MaterialPageRoute(builder: (context) => const NoticiasPage()),
|
MaterialPageRoute(builder: (context) => const NoticiasPage()),
|
||||||
);},
|
);},
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: 250.0,
|
width: 300.0,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 20.0),
|
padding: const EdgeInsets.only(bottom: 20.0),
|
||||||
child: Container(
|
child: Container(
|
||||||
@ -49,7 +49,7 @@ class MyHomePage extends StatelessWidget {
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Color.fromARGB(255, 255, 255, 255),
|
color: Color.fromARGB(255, 255, 255, 255),
|
||||||
fontSize: 27.0,
|
fontSize: 32.0,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -65,7 +65,7 @@ class MyHomePage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: 250.0,
|
width: 300.0,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 20.0),
|
padding: const EdgeInsets.only(bottom: 20.0),
|
||||||
child: Container(
|
child: Container(
|
||||||
@ -79,7 +79,7 @@ class MyHomePage extends StatelessWidget {
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: 27.0,
|
fontSize: 32.0,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -95,7 +95,7 @@ class MyHomePage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: 250.0,
|
width: 300.0,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 20.0),
|
padding: const EdgeInsets.only(bottom: 20.0),
|
||||||
child: Container(
|
child: Container(
|
||||||
@ -109,7 +109,7 @@ class MyHomePage extends StatelessWidget {
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: 27.0,
|
fontSize: 32.0,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -122,7 +122,7 @@ class MyHomePage extends StatelessWidget {
|
|||||||
launchAemetURL();
|
launchAemetURL();
|
||||||
},
|
},
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: 250.0,
|
width: 300.0,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 20.0),
|
padding: const EdgeInsets.only(bottom: 20.0),
|
||||||
child: Container(
|
child: Container(
|
||||||
@ -136,7 +136,7 @@ class MyHomePage extends StatelessWidget {
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: 27.0,
|
fontSize: 32.0,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -12,7 +12,7 @@ class NoticiasPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _NoticiasPageState extends State<NoticiasPage> {
|
class _NoticiasPageState extends State<NoticiasPage> {
|
||||||
Map<String, List<String>> noticiasPorTitulo = {};
|
Map<String, List<Future<String>>> noticiasPorTitulo = {};
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -24,46 +24,70 @@ class _NoticiasPageState extends State<NoticiasPage> {
|
|||||||
final response = await http.get(Uri.parse('http://www.crcivan.com/escaparate/noticias.cgi?idpadre=92776&idempresa=31637'));
|
final response = await http.get(Uri.parse('http://www.crcivan.com/escaparate/noticias.cgi?idpadre=92776&idempresa=31637'));
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
var document = htmlParser.parse(response.body);
|
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');
|
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++) {
|
for (int i = 0; i < tituloElements.length; i++) {
|
||||||
String titulo = tituloElements[i].text.trim();
|
String titulo = tituloElements[i].text.trim();
|
||||||
String noticia = dataElements[i].text.trim();
|
|
||||||
|
|
||||||
if (!noticiasPorTitulo.containsKey(titulo)) {
|
// Extrayendo el enlace href del elemento <a>
|
||||||
noticiasPorTitulo[titulo] = [];
|
var linkElement = tituloElements[i];
|
||||||
|
String? link = linkElement.attributes['href'];
|
||||||
|
|
||||||
|
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(() {});
|
setState(() {});
|
||||||
} else {
|
} 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 {
|
Future<String> cargarContenidoUrl(String url) async {
|
||||||
var linkElements = document.querySelectorAll('html > body > div > center > table > tbody > tr > td > div > center > table > tbody > tr > td > table > tbody > tr > td > a');
|
final response = await http.get(Uri.parse(url));
|
||||||
String? link = linkElements[i].attributes['href'];
|
|
||||||
if (response.statusCode == 200) {
|
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');
|
||||||
|
|
||||||
for (int i = 0; i < tituloElements.length; i++) {
|
String content = '';
|
||||||
String titulo = tituloElements[i].text.trim();
|
String currentParagraphContent = '';
|
||||||
String noticia = dataElements[i].text.trim();
|
|
||||||
|
|
||||||
if (!noticiasPorTitulo.containsKey(titulo)) {
|
for (var element in paragraphAndLists) {
|
||||||
noticiasPorTitulo[titulo] = [];
|
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(() {});
|
// Agregar el último párrafo si no hay lista después
|
||||||
|
if (currentParagraphContent.isNotEmpty) {
|
||||||
|
content += currentParagraphContent + '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
return content;
|
||||||
} else {
|
} else {
|
||||||
throw Exception('fallo al cargar noticias');
|
throw Exception('Fallo al cargar contenido de URL: $url');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -74,7 +98,7 @@ class _NoticiasPageState extends State<NoticiasPage> {
|
|||||||
children: [
|
children: [
|
||||||
Positioned.fill(
|
Positioned.fill(
|
||||||
child: Image(
|
child: Image(
|
||||||
image: AssetImage('assets/logo-fondo.png'),
|
image: AssetImage('assets/logo-fondo-verde.png'),
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -82,15 +106,28 @@ class _NoticiasPageState extends State<NoticiasPage> {
|
|||||||
itemCount: noticiasPorTitulo.length,
|
itemCount: noticiasPorTitulo.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
String titulo = noticiasPorTitulo.keys.elementAt(index);
|
String titulo = noticiasPorTitulo.keys.elementAt(index);
|
||||||
List<String>? noticias = noticiasPorTitulo[titulo];
|
List<Future<String>>? noticias = noticiasPorTitulo[titulo];
|
||||||
|
|
||||||
return ExpansionTile(
|
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(
|
title: Text(
|
||||||
titulo,
|
titulo,
|
||||||
style: TextStyle(fontWeight: FontWeight.bold),
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
children: noticias != null
|
children: snapshot.data!.map((noticia) {
|
||||||
? noticias.map((noticia) {
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -98,8 +135,11 @@ class _NoticiasPageState extends State<NoticiasPage> {
|
|||||||
style: TextStyle(fontSize: 16.0),
|
style: TextStyle(fontSize: 16.0),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}).toList()
|
}).toList(),
|
||||||
: [],
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@ -64,7 +64,7 @@ Widget build(BuildContext context) {
|
|||||||
// Fondo con la imagen
|
// Fondo con la imagen
|
||||||
Positioned.fill(
|
Positioned.fill(
|
||||||
child: Image(
|
child: Image(
|
||||||
image: AssetImage('assets/logo-fondo.png'),
|
image: AssetImage('assets/logo-fondo-verde.png'),
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -80,7 +80,7 @@ Widget build(BuildContext context) {
|
|||||||
if (hasMes)
|
if (hasMes)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 10.0), // Add padding to the divider
|
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
|
hasText
|
||||||
? ListTile(
|
? ListTile(
|
||||||
@ -89,7 +89,7 @@ Widget build(BuildContext context) {
|
|||||||
datos[index],
|
datos[index],
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
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)
|
if (hasMes)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 100.0), // Add padding to the divider
|
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
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user