Estructura principal de la app

This commit is contained in:
Tatiana Villa Ema 2026-05-02 02:00:58 +02:00
parent 937bd305e6
commit d96858d3c2
22 changed files with 1323 additions and 669 deletions

147
README.md
View File

@ -1,109 +1,104 @@
# El Faro del Peregrino
Una aplicación espiritual para acompañar el camino interior y comunitario.
El Faro del Peregrino es una aplicación diseñada para ofrecer luz, guía y herramientas prácticas a quienes desean profundizar en su vida espiritual. Su propósito es integrar oración, reflexión, comunidad y belleza visual en una experiencia sencilla y significativa.
Una aplicación para acompañar el camino interior y comunitario, integrando oración, reflexión y comunidad en una experiencia visualmente inspiradora.
---
## Objetivos del proyecto
- Crear una app que acompañe el crecimiento espiritual personal.
- Integrar recursos como oraciones, meditaciones, lecturas y seguimiento del camino interior.
- Diseñar una interfaz cálida, estética y accesible.
- Construir una base sólida para futuras funcionalidades como:
- Comunidad de peregrinos
- Diario espiritual
- Ritmos diarios (Laudes, Vísperas, etc.)
- Notificaciones de oración
- Contenidos multimedia
## ✨ Propósito
El Faro del Peregrino nace para ofrecer luz, guía y herramientas prácticas a quienes desean profundizar en su vida espiritual. Busca integrar recursos de oración, reflexión y comunidad en una app sencilla, cálida y significativa.
---
## Tecnologías utilizadas
Este proyecto está construido con:
## 🎯 Objetivos
- Java / Kotlin (según evolucione el código del módulo app/)
- Gradle como sistema de construcción
- Android Studio como entorno de desarrollo
- Estructura modular preparada para escalar
- Acompañar el crecimiento espiritual personal y comunitario.
- Integrar oraciones, meditaciones, lecturas y seguimiento del camino interior.
- Ofrecer una interfaz estética, accesible y acogedora.
- Sentar las bases para futuras funcionalidades:
- Comunidad de peregrinos
- Diario espiritual
- Ritmos diarios (Laudes, Vísperas, etc.)
- Notificaciones de oración
- Contenidos multimedia
---
## Estructura del repositorio
`
## 🛠️ Tecnologías
- **Lenguajes:** Java / Kotlin (según evolución del módulo `app/`)
- **Build:** Gradle (con wrapper incluido)
- **IDE:** Android Studio (recomendado Flamingo o superior)
- **Arquitectura:** Modular y escalable
---
## 📁 Estructura del repositorio
```
el-faro-del-peregrino/
├── app/
├── gradle/
├── build.gradle.kts
├── settings.gradle.kts
├── gradle.properties
└── .idea/
`
├── app/ # Código principal de la app
├── gradle/ # Configuración de Gradle
├── build.gradle.kts # Build script raíz
├── settings.gradle.kts # Configuración de módulos
├── gradle.properties # Propiedades globales
└── .idea/ # Configuración de Android Studio
```
---
## Cómo ejecutar el proyecto
## 🚀 Cómo ejecutar el proyecto
1. Requisitos previos
- Android Studio Flamingo o superior
- JDK 17+
- Gradle (incluido en el wrapper)
1. **Requisitos previos**
- Android Studio Flamingo o superior
- JDK 17+
- Gradle (incluido en el wrapper)
2. Clonar el repositorio
`bash
git clone https://git.tatvil.es/tatiana/el-faro-del-peregrino.git
cd el-faro-del-peregrino
`
2. **Clonar el repositorio**
```bash
git clone https://git.tatvil.es/tatiana/el-faro-del-peregrino.git
cd el-faro-del-peregrino
```
3. Abrir en Android Studio
- Selecciona Open
- Elige la carpeta del proyecto
- Android Studio descargará dependencias y sincronizará Gradle automáticamente
3. **Abrir en Android Studio**
- Selecciona *Open*
- Elige la carpeta del proyecto
- Android Studio descargará dependencias y sincronizará Gradle automáticamente
4. Ejecutar la app
- Conecta un dispositivo o usa un emulador
- Pulsa ▶️ Run
4. **Ejecutar la app**
- Conecta un dispositivo o usa un emulador
- Pulsa ▶️ *Run*
---
🗺️ Roadmap inicial
Este roadmap está alineado con el estilo profesional que ya usas en GitHub Issues.
## 🗺️ Roadmap
Versión 0.1 — Estructura base
- [ ] Configuración inicial del proyecto
- [ ] Pantalla de bienvenida
- [ ] Navegación básica
**Versión 0.1 — Estructura base**
- [ ] Configuración inicial del proyecto
- [ ] Pantalla de bienvenida
- [ ] Navegación básica
- [ ] Tema visual inicial (colores, tipografías, iconografía)
Versión 0.2 — Contenidos espirituales
- [ ] Módulo de oraciones
- [ ] Lecturas del día
- [ ] Modo oscuro contemplativo
**Versión 0.2 — Contenidos espirituales**
- [ ] Módulo de oraciones
- [ ] Lecturas del día
- [ ] Modo oscuro contemplativo
Versión 0.3 — Herramientas del peregrino
- [ ] Diario espiritual
- [ ] Seguimiento del camino
- [ ] Notificaciones de ritmo diario
**Versión 0.3 — Herramientas del peregrino**
- [ ] Diario espiritual
- [ ] Seguimiento del camino
- [ ] Notificaciones de ritmo diario
Versión 1.0 — Comunidad
- [ ] Perfil del peregrino
- [ ] Espacios de oración compartida
- [ ] Mensajes y peticiones
**Versión 1.0 — Comunidad**
- [ ] Perfil del peregrino
- [ ] Espacios de oración compartida
- [ ] Mensajes y peticiones
---
🤝 Contribuciones
Este proyecto está en desarrollo activo.
Las ideas, mejoras y bugs se gestionan mediante GitHub Issues siguiendo un flujo profesional.
## 🌅 Inspiración
---
> “El faro no navega por ti, pero ilumina el camino.”
📜 Licencia
Pendiente de definir.
Recomendación: MIT o Apache 2.0 para proyectos abiertos; licencia privada si será app personal o comercial.
---
🕯️ Inspiración
> “El faro no navega por ti, pero ilumina el camino.”
Este proyecto nace para ofrecer luz, calma y dirección en medio del viaje interior.
Este proyecto busca ofrecer luz, calma y dirección en el viaje interior.

View File

@ -46,5 +46,6 @@ dependencies {
implementation("com.google.android.gms:play-services-location:21.3.0")
implementation(libs.volley)
implementation(libs.glide)
implementation(libs.mpandroidchart)
annotationProcessor(libs.glide.compiler)
}

View File

@ -7,6 +7,13 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<queries>
<package android:name="com.google.android.apps.maps" />
<intent>
<action android:name="android.intent.action.DIAL" />
</intent>
</queries>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
@ -31,6 +38,16 @@
android:label="Detalle de la Etapa"
android:parentActivityName=".MainActivity">
</activity>
<activity
android:name=".EtapasActivity"
android:label="Etapas del Camino"
android:parentActivityName=".MainActivity">
</activity>
<activity
android:name=".DetalleServicioActivity"
android:label="Detalle del Servicio"
android:parentActivityName=".DetalleEtapaActivity">
</activity>
</application>
</manifest>

View File

@ -1,5 +1,6 @@
package es.tatvil.elfarodelperegrino;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -40,6 +41,12 @@ public class AlbergueAdapter extends RecyclerView.Adapter<AlbergueAdapter.Alberg
float distanciaKm = results[0] / 1000;
holder.tvDistancia.setText(String.format(Locale.getDefault(), "A %.1f km del destino", distanciaKm));
holder.itemView.setOnClickListener(v -> {
Intent intent = new Intent(v.getContext(), DetalleServicioActivity.class);
intent.putExtra("objeto", albergue);
v.getContext().startActivity(intent);
});
}
@Override

View File

@ -1,10 +1,13 @@
package es.tatvil.elfarodelperegrino;
import android.graphics.Color;
import android.location.Location;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
@ -17,12 +20,20 @@ import com.android.volley.RequestQueue;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import com.bumptech.glide.Glide;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
public class DetalleEtapaActivity extends AppCompatActivity {
@ -39,24 +50,34 @@ public class DetalleEtapaActivity extends AppCompatActivity {
ImageView ivImagen = findViewById(R.id.ivDetalleImagen);
TextView tvTitulo = findViewById(R.id.tvDetalleTitulo);
TextView tvDistancia = findViewById(R.id.tvDetalleDistancia);
TextView tvDesnivelPos = findViewById(R.id.tvDetalleDesnivelPos);
TextView tvDesnivelNeg = findViewById(R.id.tvDetalleDesnivelNeg);
TextView tvHistoria = findViewById(R.id.tvDetalleHistoria);
TextView tvReflexion = findViewById(R.id.tvDetalleReflexion);
TextView tvClima = findViewById(R.id.tvDetalleClima);
tvTitulo.setText(etapa.getOrigen() + " - " + etapa.getDestino());
tvDistancia.setText("Distancia: " + etapa.getDistancia() + " km");
tvDistancia.setText(etapa.getDistancia() + " km");
tvDesnivelPos.setText("+" + etapa.getDesnivelPositivo() + "m");
tvDesnivelNeg.setText("-" + etapa.getDesnivelNegativo() + "m");
tvHistoria.setText(etapa.getHitoHistorico());
tvReflexion.setText(etapa.getReflexionEspiritual());
configurarGrafico(findViewById(R.id.elevationChart), etapa);
Glide.with(this)
.load(etapa.getImagenUrl())
.placeholder(android.R.drawable.ic_menu_gallery)
.into(ivImagen);
obtenerClima(etapa.getLatitud(), etapa.getLongitud(), tvClima);
obtenerClimaYPrevision(etapa.getLatitud(), etapa.getLongitud(), tvClima, findViewById(R.id.layoutForecast));
findViewById(R.id.btnVerClima).setOnClickListener(v ->
obtenerClima(etapa.getLatitud(), etapa.getLongitud(), tvClima));
// Botón Mapa
findViewById(R.id.btnVerMapa).setOnClickListener(v -> {
String uri = "geo:" + etapa.getLatitud() + "," + etapa.getLongitud() + "?q=" + etapa.getDestino();
android.content.Intent intent = new android.content.Intent(android.content.Intent.ACTION_VIEW, android.net.Uri.parse(uri));
startActivity(intent);
});
// Botón Albergues
findViewById(R.id.btnVerAlbergues).setOnClickListener(v -> {
@ -76,7 +97,7 @@ public class DetalleEtapaActivity extends AppCompatActivity {
if (cercanas.isEmpty()) {
Toast.makeText(this, "No hay iglesias registradas cerca", Toast.LENGTH_SHORT).show();
} else {
mostrarDialogoSimple("Iglesias cercanas", cercanas);
mostrarDialogoServicios("Iglesias cercanas", cercanas, etapa);
}
});
@ -92,7 +113,7 @@ public class DetalleEtapaActivity extends AppCompatActivity {
if (cercanos.isEmpty()) {
Toast.makeText(this, "No hay restaurantes registrados cerca", Toast.LENGTH_SHORT).show();
} else {
mostrarDialogoSimple("Restaurantes cercanos", cercanos);
mostrarDialogoServicios("Restaurantes cercanos", cercanos, etapa);
}
});
}
@ -126,18 +147,17 @@ public class DetalleEtapaActivity extends AppCompatActivity {
.show();
}
private void mostrarDialogoSimple(String titulo, List<?> items) {
StringBuilder sb = new StringBuilder();
for (Object item : items) {
if (item instanceof Iglesia) sb.append("").append(((Iglesia) item).getNombre()).append("\n");
if (item instanceof Restaurante) sb.append("").append(((Restaurante) item).getNombre()).append("\n");
}
private void mostrarDialogoServicios(String titulo, List<?> items, Etapa etapa) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
View view = LayoutInflater.from(this).inflate(R.layout.dialog_lista_albergues, null);
RecyclerView rv = view.findViewById(R.id.rvDialogo);
rv.setLayoutManager(new LinearLayoutManager(this));
rv.setAdapter(new SimpleServicioAdapter(items, etapa.getLatitud(), etapa.getLongitud()));
new AlertDialog.Builder(this)
.setTitle(titulo)
.setMessage(sb.toString())
.setPositiveButton("OK", null)
.show();
builder.setTitle(titulo)
.setView(view)
.setPositiveButton("Cerrar", null)
.show();
}
private double calcularDistancia(double lat1, double lon1, double lat2, double lon2) {
@ -146,21 +166,100 @@ public class DetalleEtapaActivity extends AppCompatActivity {
return results[0] / 1000; // Retorna km
}
private void obtenerClima(double lat, double lon, TextView tvClima) {
String url = "https://api.openweathermap.org/data/2.5/weather?lat=" + lat + "&lon=" + lon + "&appid=" + API_KEY + "&units=metric&lang=es";
private void configurarGrafico(LineChart chart, Etapa etapa) {
List<Entry> entries = new ArrayList<>();
List<Integer> perfil = etapa.getPerfilElevacion();
for (int i = 0; i < perfil.size(); i++) {
entries.add(new Entry(i, perfil.get(i)));
}
LineDataSet dataSet = new LineDataSet(entries, "Elevación (m)");
dataSet.setColor(Color.parseColor("#4CAF50"));
dataSet.setCircleColor(Color.parseColor("#4CAF50"));
dataSet.setLineWidth(2f);
dataSet.setCircleRadius(3f);
dataSet.setDrawCircleHole(false);
dataSet.setValueTextColor(Color.WHITE);
dataSet.setDrawFilled(true);
dataSet.setFillDrawable(getResources().getDrawable(R.drawable.ic_launcher_background)); // O un gradiente simple
dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
LineData lineData = new LineData(dataSet);
chart.setData(lineData);
chart.getDescription().setEnabled(false);
chart.getLegend().setTextColor(Color.WHITE);
chart.getXAxis().setTextColor(Color.WHITE);
chart.getAxisLeft().setTextColor(Color.WHITE);
chart.getAxisRight().setEnabled(false);
chart.animateX(1500);
chart.invalidate();
}
private void obtenerClimaYPrevision(double lat, double lon, TextView tvClima, LinearLayout layoutForecast) {
// Clima actual
String urlWeather = "https://api.openweathermap.org/data/2.5/weather?lat=" + lat + "&lon=" + lon + "&appid=" + API_KEY + "&units=metric&lang=es";
// Previsión (5 días cada 3 horas)
String urlForecast = "https://api.openweathermap.org/data/2.5/forecast?lat=" + lat + "&lon=" + lon + "&appid=" + API_KEY + "&units=metric&lang=es";
RequestQueue queue = Volley.newRequestQueue(this);
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null,
// Request para clima actual
JsonObjectRequest requestWeather = new JsonObjectRequest(Request.Method.GET, urlWeather, null,
response -> {
try {
JSONObject main = response.getJSONObject("main");
double temp = main.getDouble("temp");
String desc = response.getJSONArray("weather").getJSONObject(0).getString("description");
tvClima.setText("Clima actual: " + temp + "°C, " + desc);
tvClima.setText("Hoy: " + temp + "°C, " + desc);
} catch (JSONException e) {
tvClima.setText("Error al procesar clima");
tvClima.setText("Error en clima actual");
}
},
error -> tvClima.setText("Error al obtener clima"));
queue.add(request);
}, error -> tvClima.setText("Error al conectar con clima"));
// Request para previsión
JsonObjectRequest requestForecast = new JsonObjectRequest(Request.Method.GET, urlForecast, null,
response -> {
try {
JSONArray list = response.getJSONArray("list");
layoutForecast.removeAllViews();
// Tomamos un punto por día (cada 8 registros son 24h aprox)
for (int i = 8; i < list.length() && i <= 24; i += 8) {
JSONObject dayObj = list.getJSONObject(i);
double temp = dayObj.getJSONObject("main").getDouble("temp");
String desc = dayObj.getJSONArray("weather").getJSONObject(0).getString("description");
long dt = dayObj.getLong("dt") * 1000;
String fecha = new SimpleDateFormat("EEE", new Locale("es", "ES")).format(new Date(dt));
agregarVistaPrevision(layoutForecast, fecha, temp, desc);
}
} catch (JSONException e) {
e.printStackTrace();
}
}, error -> {});
queue.add(requestWeather);
queue.add(requestForecast);
}
private void agregarVistaPrevision(LinearLayout layout, String dia, double temp, String desc) {
LinearLayout v = new LinearLayout(this);
v.setOrientation(LinearLayout.VERTICAL);
v.setLayoutParams(new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f));
v.setGravity(Gravity.CENTER);
TextView tvDia = new TextView(this);
tvDia.setText(dia.toUpperCase());
tvDia.setTextColor(Color.WHITE);
tvDia.setTextSize(12);
TextView tvTemp = new TextView(this);
tvTemp.setText((int)temp + "°");
tvTemp.setTextColor(Color.parseColor("#FFEB3B"));
tvTemp.setTextSize(16);
tvTemp.setTypeface(null, android.graphics.Typeface.BOLD);
layout.addView(v);
v.addView(tvDia);
v.addView(tvTemp);
}
}

View File

@ -0,0 +1,94 @@
package es.tatvil.elfarodelperegrino;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.button.MaterialButton;
public class DetalleServicioActivity extends AppCompatActivity {
private String nombre, telefono, tipo, descripcion;
private double latitud, longitud;
private boolean tieneCocina;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detalle_servicio);
// Obtener datos del Intent
Object object = getIntent().getSerializableExtra("objeto");
if (object instanceof Albergue) {
Albergue a = (Albergue) object;
nombre = a.getNombre();
telefono = a.getTelefono();
tipo = a.getTipo();
descripcion = a.getComentario();
latitud = a.getLatitud();
longitud = a.getLongitud();
tieneCocina = a.isTieneCocina();
} else if (object instanceof Restaurante) {
Restaurante r = (Restaurante) object;
nombre = r.getNombre();
telefono = ""; // Por ahora no hay en JSON
tipo = getString(R.string.action_food).replace("\n", " ");
descripcion = getString(R.string.msg_food_place);
latitud = r.getLatitud();
longitud = r.getLongitud();
} else if (object instanceof Iglesia) {
Iglesia i = (Iglesia) object;
nombre = i.getNombre();
telefono = "";
tipo = getString(R.string.msg_interest_place); // Usando un string descriptivo como tipo
descripcion = getString(R.string.msg_interest_place);
latitud = i.getLatitud();
longitud = i.getLongitud();
}
// Vincular vistas
TextView tvNombre = findViewById(R.id.tvDetalleNombre);
TextView tvTipo = findViewById(R.id.tvDetalleTipo);
TextView tvDescripcion = findViewById(R.id.tvDetalleDescripcion);
TextView tvCocina = findViewById(R.id.tvDetalleCocina);
View layoutExtras = findViewById(R.id.layoutExtras);
MaterialButton btnLlamar = findViewById(R.id.btnLlamar);
MaterialButton btnComoLlegar = findViewById(R.id.btnComoLlegar);
tvNombre.setText(nombre);
tvTipo.setText(tipo);
tvDescripcion.setText(descripcion != null && !descripcion.isEmpty() ? descripcion : getString(R.string.msg_no_description));
if (tieneCocina) {
layoutExtras.setVisibility(View.VISIBLE);
tvCocina.setVisibility(View.VISIBLE);
}
if (telefono == null || telefono.isEmpty() || telefono.equals("Sin teléfono")) {
btnLlamar.setVisibility(View.GONE);
} else {
btnLlamar.setOnClickListener(v -> {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:" + telefono));
startActivity(intent);
});
}
btnComoLlegar.setOnClickListener(v -> {
String uri = String.format(java.util.Locale.US, "google.navigation:q=%f,%f&mode=w", latitud, longitud);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
intent.setPackage("com.google.android.apps.maps");
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
} else {
// Fallback a navegador si no hay Google Maps
String webUri = String.format(java.util.Locale.US, "https://www.google.com/maps/dir/?api=1&destination=%f,%f&travelmode=walking", latitud, longitud);
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(webUri)));
}
});
}
}

View File

@ -1,6 +1,8 @@
package es.tatvil.elfarodelperegrino;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class Etapa implements Serializable {
private String nombre;
@ -14,6 +16,9 @@ public class Etapa implements Serializable {
private String hitoHistorico;
private double latitud, longitud;
private String imagenUrl;
private int desnivelPositivo;
private int desnivelNegativo;
private List<Integer> perfilElevacion;
public Etapa(String nombre, String origen, String destino, String ruta, String camino, double distancia,
int dificultad, String reflexionEspiritual, String hitoHistorico,
@ -30,11 +35,29 @@ public class Etapa implements Serializable {
this.latitud = latitud;
this.longitud = longitud;
this.imagenUrl = "https://picsum.photos/seed/" + nombre.replace(" ", "") + "/800/400";
// Valores por defecto para el ejemplo
this.desnivelPositivo = (int) (distancia * 15);
this.desnivelNegativo = (int) (distancia * 12);
this.perfilElevacion = generarPerfilMock(distancia);
}
private List<Integer> generarPerfilMock(double dist) {
List<Integer> perfil = new ArrayList<>();
int base = 100 + (int)(Math.random() * 200);
for (int i = 0; i <= 10; i++) {
perfil.add(base + (int)(Math.random() * 150));
}
return perfil;
}
// Getters
public String getImagenUrl() { return imagenUrl; }
public List<Integer> getPerfilElevacion() { return perfilElevacion; }
public int getDesnivelPositivo() { return desnivelPositivo; }
public int getDesnivelNegativo() { return desnivelNegativo; }
public void setDesnivelPositivo(int desnivelPositivo) { this.desnivelPositivo = desnivelPositivo; }
public void setDesnivelNegativo(int desnivelNegativo) { this.desnivelNegativo = desnivelNegativo; }
public void setImagenUrl(String imagenUrl) { this.imagenUrl = imagenUrl; }
public String getImagenUrl() { return imagenUrl; }
public String getNombre() { return nombre; }
public String getOrigen() { return origen; }
public String getDestino() { return destino; }

View File

@ -0,0 +1,115 @@
package es.tatvil.elfarodelperegrino;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class EtapasActivity extends AppCompatActivity {
private FusedLocationProviderClient fusedLocationClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
// 1. SIEMPRE debes llamar al super y establecer la vista
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_etapas); // Esto vincula el XML activity_etapas
// 2. Ahora , inicializamos el RecyclerView después de que la vista exista
RecyclerView recyclerView = findViewById(R.id.recyclerViewEtapas);
// 3. Configuración del LayoutManager
recyclerView.setLayoutManager(new LinearLayoutManager(this));
// 4. Configuración del Spinner para seleccionar el camino
Spinner spinnerCaminos = findViewById(R.id.spinnerCaminos);
String[] opcionesCaminos = {"Norte", "Francés"};
ArrayAdapter<String> adapterCaminos = new ArrayAdapter<>(this,
android.R.layout.simple_spinner_item, opcionesCaminos);
adapterCaminos.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerCaminos.setAdapter(adapterCaminos);
// 5. Configuración del Spinner para distancia máxima
Spinner spinnerDistancia = findViewById(R.id.spinnerDistancia);
String[] opcionesDistancia = {"Sin límite", "15 km", "20 km", "25 km"};
ArrayAdapter<String> adapterDistancia = new ArrayAdapter<>(this,
android.R.layout.simple_spinner_item, opcionesDistancia);
adapterDistancia.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerDistancia.setAdapter(adapterDistancia);
AdapterView.OnItemSelectedListener listener = new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String camino = spinnerCaminos.getSelectedItem().toString();
String distStr = spinnerDistancia.getSelectedItem().toString();
double maxDist = Double.MAX_VALUE;
if (!distStr.equals("Sin límite")) {
maxDist = Double.parseDouble(distStr.split(" ")[0]);
}
actualizarListaEtapas(camino, maxDist, recyclerView);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {}
};
spinnerCaminos.setOnItemSelectedListener(listener);
spinnerDistancia.setOnItemSelectedListener(listener);
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
obtenerUbicacionActual();
}
private void actualizarListaEtapas(String camino, double maxDistancia, RecyclerView recyclerView) {
List<Etapa> todas = CaminoData.getEtapasPorCamino(this, camino);
List<Etapa> filtradas = new ArrayList<>();
for (Etapa e : todas) {
if (e.getDistancia() <= maxDistancia) {
filtradas.add(e);
}
}
EtapaAdapter adapter = new EtapaAdapter(filtradas);
recyclerView.setAdapter(adapter);
}
private void obtenerUbicacionActual() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
fusedLocationClient.getLastLocation().addOnSuccessListener(this, location -> {
if (location != null) {
// Futura implementación: resaltar etapa más cercana
}
});
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 1) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
obtenerUbicacionActual();
}
}
}
}

View File

@ -1,174 +1,46 @@
package es.tatvil.elfarodelperegrino;
import android.Manifest;
import android.content.pm.PackageManager;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private FusedLocationProviderClient fusedLocationClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
// 1. SIEMPRE debes llamar al super y establecer la vista
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // Esto vincula el XML activity_main
setContentView(R.layout.activity_main);
// 2. Ahora , inicializamos el RecyclerView después de que la vista exista
RecyclerView recyclerView = findViewById(R.id.recyclerViewEtapas);
// 3. Configuración del LayoutManager
recyclerView.setLayoutManager(new LinearLayoutManager(this));
// 4. Configuración del Spinner para seleccionar el camino
Spinner spinner = findViewById(R.id.spinnerCaminos);
String[] opcionesCaminos = {"Norte", "Francés"};
ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(this,
android.R.layout.simple_spinner_item, opcionesCaminos);
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(spinnerAdapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String caminoSeleccionado = opcionesCaminos[position];
actualizarListaEtapas(caminoSeleccionado, recyclerView);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
// --- SECCIÓN RUTA ---
findViewById(R.id.btnMap).setOnClickListener(v -> {
Intent intent = new Intent(MainActivity.this, EtapasActivity.class);
startActivity(intent);
});
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
obtenerUbicacionActual();
// --- SECCIÓN SERVICIOS ---
findViewById(R.id.btnSleep).setOnClickListener(v -> {
Toast.makeText(this, "Funcionalidad de Alojamiento próximamente", Toast.LENGTH_SHORT).show();
});
findViewById(R.id.btnFood).setOnClickListener(v -> {
Toast.makeText(this, "Funcionalidad de Restaurantes próximamente", Toast.LENGTH_SHORT).show();
});
// --- SECCIÓN MI CAMINO ---
findViewById(R.id.btnDiary).setOnClickListener(v -> {
Toast.makeText(this, "Funcionalidad de Diario próximamente", Toast.LENGTH_SHORT).show();
});
findViewById(R.id.btnRegister).setOnClickListener(v -> {
Toast.makeText(this, "Funcionalidad de Sellar Credencial próximamente", Toast.LENGTH_SHORT).show();
});
findViewById(R.id.btnTraining).setOnClickListener(v -> {
Toast.makeText(this, "Funcionalidad de Entrenamiento próximamente", Toast.LENGTH_SHORT).show();
});
}
private void actualizarListaEtapas(String camino, RecyclerView recyclerView) {
List<Etapa> etapas = CaminoData.getEtapasPorCamino(this, camino);
EtapaAdapter adapter = new EtapaAdapter(etapas);
recyclerView.setAdapter(adapter);
}
private void obtenerUbicacionActual() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
fusedLocationClient.getLastLocation().addOnSuccessListener(this, location -> {
if (location != null) {
double miLat = location.getLatitude();
double miLon = location.getLongitude();
// Aquí se compararía con las etapas
}
});
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 1) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
obtenerUbicacionActual();
}
}
}
private List<Etapa> cargarEtapasDesdeJSON() {
List<Etapa> lista = new ArrayList<>();
try {
InputStream is = getResources().openRawResource(R.raw.etapas);
byte[] buffer = new byte[is.available()];
is.read(buffer);
is.close();
String json = new String(buffer, "UTF-8");
JSONArray jsonArray = new JSONArray(json);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject obj = jsonArray.getJSONObject(i);
lista.add(new Etapa(
obj.getString("nombre"),
obj.optString("origen", ""),
obj.optString("destino", ""),
obj.optString("ruta", obj.optString("origen") + " - " + obj.optString("destino")),
obj.optString("camino", "Norte"),
obj.getDouble("distancia"),
obj.optInt("dificultad", 0),
obj.optString("reflexionEspiritual", obj.optString("reflexion", "")),
obj.optString("hitoHistorico", obj.optString("historia", "")),
obj.getDouble("latitud"),
obj.getDouble("longitud")
));
}
} catch (Exception e) {
e.printStackTrace();
}
return lista;
}
private List<Etapa> leerEtapasDesdeRaw() {
List<Etapa> lista = new ArrayList<>();
try {
// Abrimos el archivo etapas.json que debes crear en res/raw
InputStream is = getResources().openRawResource(R.raw.etapas);
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
String jsonString = new String(buffer, "UTF-8");
JSONArray jsonArray = new JSONArray(jsonString);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject obj = jsonArray.getJSONObject(i);
lista.add(new Etapa(
obj.getString("nombre"),
obj.optString("origen", ""),
obj.optString("destino", ""),
obj.optString("ruta", obj.optString("origen") + " - " + obj.optString("destino")),
obj.optString("camino", "Norte"),
obj.getDouble("distancia"),
obj.optInt("dificultad", 0),
obj.optString("reflexionEspiritual", obj.optString("reflexion", "")),
obj.optString("hitoHistorico", obj.optString("historia", "")),
obj.getDouble("latitud"),
obj.getDouble("longitud")
));
}
} catch (Exception e) {
e.printStackTrace();
}
return lista;
}
// Método para calcular distancia entre dos puntos (Fórmula de Haversine simplificada)
public double calcularDistancia(double lat1, double lon1, double lat2, double lon2) {
double theta = lon1 - lon2;
double dist = Math.sin(Math.toRadians(lat1)) * Math.sin(Math.toRadians(lat2)) +
Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
Math.cos(Math.toRadians(theta));
dist = Math.acos(dist);
dist = Math.toDegrees(dist);
return dist * 60 * 1.1515 * 1.609344; // Retorna Kilómetros
}
}
}

View File

@ -1,22 +0,0 @@
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Aquí conectas los botones
findViewById(R.id.btnTraining).setOnClickListener(v -> {
// TODO: abrir pantalla de entrenamiento
});
findViewById(R.id.btnDiary).setOnClickListener(v -> {
// TODO: abrir pantalla del diario
});
// ... y así con los demás
}
}
})
})

View File

@ -0,0 +1,85 @@
package es.tatvil.elfarodelperegrino;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.io.Serializable;
import java.util.List;
import java.util.Locale;
public class SimpleServicioAdapter extends RecyclerView.Adapter<SimpleServicioAdapter.ViewHolder> {
private List<?> items;
private double refLat, refLon;
public SimpleServicioAdapter(List<?> items, double refLat, double refLon) {
this.items = items;
this.refLat = refLat;
this.refLon = refLon;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_albergue, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Object item = items.get(position);
String nombre = "";
double lat = 0, lon = 0;
String tipo = "";
if (item instanceof Iglesia) {
Iglesia i = (Iglesia) item;
nombre = i.getNombre();
lat = i.getLatitud();
lon = i.getLongitud();
tipo = "Iglesia";
} else if (item instanceof Restaurante) {
Restaurante r = (Restaurante) item;
nombre = r.getNombre();
lat = r.getLatitud();
lon = r.getLongitud();
tipo = "Restaurante";
}
holder.tvNombre.setText(nombre);
holder.tvTipo.setText(tipo);
holder.tvTelefono.setVisibility(View.GONE);
float[] results = new float[1];
android.location.Location.distanceBetween(refLat, refLon, lat, lon, results);
float distanciaKm = results[0] / 1000;
holder.tvDistancia.setText(String.format(Locale.getDefault(), "A %.1f km", distanciaKm));
holder.itemView.setOnClickListener(v -> {
Intent intent = new Intent(v.getContext(), DetalleServicioActivity.class);
intent.putExtra("objeto", (Serializable) item);
v.getContext().startActivity(intent);
});
}
@Override
public int getItemCount() {
return items.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView tvNombre, tvTipo, tvDistancia, tvTelefono;
public ViewHolder(@NonNull View itemView) {
super(itemView);
tvNombre = itemView.findViewById(R.id.tvAlbergueNombre);
tvTipo = itemView.findViewById(R.id.tvAlbergueTipo);
tvDistancia = itemView.findViewById(R.id.tvAlbergueDistancia);
tvTelefono = itemView.findViewById(R.id.tvAlbergueTelefono);
}
}
}

View File

@ -1,170 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:fillColor="#003366"
android:pathData="M0,0h108v108h-108z" />
<!-- Subtle circular glow in the center -->
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>
android:pathData="M54,54m-40,0a40,40 0,1 1,80 0a40,40 0,1 1,-80 0">
<aapt:attr name="android:fillColor">
<gradient
android:centerX="54"
android:centerY="54"
android:gradientRadius="45"
android:type="radial">
<item android:color="#1AFFFFFF" android:offset="0.0" />
<item android:color="#00FFFFFF" android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
</vector>

View File

@ -4,27 +4,62 @@
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<!-- Lighthouse Body -->
<path
android:pathData="M44,85 L64,85 L60,35 L48,35 Z"
android:fillColor="#E0E0E0" />
<path
android:pathData="M46,55 L62,55 L61,65 L47,65 Z"
android:fillColor="#B71C1C" /> <!-- Red stripe -->
<!-- Top Lantern Room -->
<path
android:pathData="M46,35 L62,35 L62,25 L46,25 Z"
android:fillColor="#333333" />
<path
android:pathData="M48,25 L60,25 L54,18 Z"
android:fillColor="#333333" />
<!-- Light Beam (Left) -->
<path
android:pathData="M48,30 L15,15 L15,45 Z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:startX="48"
android:startY="30"
android:endX="15"
android:endY="30"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
<item android:color="#B3FFD700" android:offset="0.0" />
<item android:color="#00FFD700" android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<!-- Light Beam (Right) -->
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
android:pathData="M60,30 L93,15 L93,45 Z">
<aapt:attr name="android:fillColor">
<gradient
android:startX="60"
android:startY="30"
android:endX="93"
android:endY="30"
android:type="linear">
<item android:color="#B3FFD700" android:offset="0.0" />
<item android:color="#00FFD700" android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<!-- Scallop Shell (Concha de Santiago) at the bottom -->
<path
android:pathData="M54,88 C48,88 44,92 44,96 C44,101 48,104 54,104 C60,104 64,101 64,96 C64,92 60,88 54,88 Z"
android:fillColor="#FFD700" />
<!-- Ridges on the shell -->
<path android:pathData="M54,90 L54,102" android:strokeColor="#B29600" android:strokeWidth="1" />
<path android:pathData="M50,91 L52,101" android:strokeColor="#B29600" android:strokeWidth="1" />
<path android:pathData="M58,91 L56,101" android:strokeColor="#B29600" android:strokeWidth="1" />
</vector>

View File

@ -1,145 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- Saludo -->
<TextView
android:id="@+id/txtGreeting"
android:text="Buen Camino, Tatiana"
android:textSize="24sp"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<!-- Fecha -->
<TextView
android:id="@+id/txtDate"
android:text="Sábado, 2 de mayo de 2026"
android:textSize="16sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<!-- Tarjeta del tiempo -->
<LinearLayout
android:orientation="vertical"
android:padding="16dp"
android:background="#1E88E5"
android:layout_marginTop="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/txtLocation"
android:text="📍 Las Rozas de Madrid"
android:textColor="@android:color/white"
android:textSize="16sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/txtWeatherToday"
android:text="Hoy: 11ºC - 19ºC · 60%"
android:textColor="@android:color/white"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/txtWeatherTomorrow"
android:text="Mañana: 14ºC - 20ºC · 17%"
android:textColor="@android:color/white"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<!-- Grid de botones -->
<GridLayout
android:id="@+id/gridButtons"
android:columnCount="2"
android:rowCount="4"
android:layout_marginTop="24dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- Cada botón -->
<Button
android:id="@+id/btnTraining"
android:text="Entrenamiento"
android:layout_width="0dp"
android:layout_height="80dp"
android:layout_columnWeight="1"
android:layout_margin="8dp"/>
<Button
android:id="@+id/btnMap"
android:text="Mapa y etapas"
android:layout_width="0dp"
android:layout_height="80dp"
android:layout_columnWeight="1"
android:layout_margin="8dp"/>
<Button
android:id="@+id/btnFood"
android:text="Dónde comer"
android:layout_width="0dp"
android:layout_height="80dp"
android:layout_columnWeight="1"
android:layout_margin="8dp"/>
<Button
android:id="@+id/btnSleep"
android:text="Dónde dormir"
android:layout_width="0dp"
android:layout_height="80dp"
android:layout_columnWeight="1"
android:layout_margin="8dp"/>
<Button
android:id="@+id/btnServices"
android:text="Servicios útiles"
android:layout_width="0dp"
android:layout_height="80dp"
android:layout_columnWeight="1"
android:layout_margin="8dp"/>
<Button
android:id="@+id/btnRegister"
android:text="Registrar paso"
android:layout_width="0dp"
android:layout_height="80dp"
android:layout_columnWeight="1"
android:layout_margin="8dp"/>
<Button
android:id="@+id/btnDiary"
android:text="Mi diario"
android:layout_width="0dp"
android:layout_height="80dp"
android:layout_columnWeight="1"
android:layout_margin="8dp"/>
<Button
android:id="@+id/btnMessages"
android:text="Mensajes del camino"
android:layout_width="0dp"
android:layout_height="80dp"
android:layout_columnWeight="1"
android:layout_margin="8dp"/>
</GridLayout>
<!-- Frase final -->
<TextView
android:id="@+id/txtQuote"
android:text="El camino me enseñó que el verdadero lujo es el que nos dedicamos a nosotros mismos."
android:layout_marginTop="24dp"
android:textSize="14sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</ScrollView>

View File

@ -28,62 +28,155 @@
android:text="Nombre de la Etapa"
android:layout_marginBottom="16dp"/>
<TextView
android:id="@+id/tvDetalleDistancia"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textColor="#BBBBBB"
android:text="Distancia: 24 km"
android:layout_marginBottom="24dp"/>
android:orientation="horizontal"
android:layout_marginBottom="16dp"
android:baselineAligned="false">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Historia y Hitos"
android:textStyle="bold"
android:textColor="@color/text_primary"
android:layout_marginBottom="8dp"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Distancia"
android:textColor="#BBBBBB"
android:textSize="12sp"/>
<TextView
android:id="@+id/tvDetalleDistancia"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/text_primary"
android:text="24 km"/>
</LinearLayout>
<TextView
android:id="@+id/tvDetalleHistoria"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/text_primary"
android:text="Cargando historia..."
android:layout_marginBottom="24dp"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Desnivel +"
android:textColor="#BBBBBB"
android:textSize="12sp"/>
<TextView
android:id="@+id/tvDetalleDesnivelPos"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="#4CAF50"
android:text="+450m"/>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Reflexión Espiritual"
android:textStyle="bold"
android:textColor="@color/text_primary"
android:layout_marginBottom="8dp"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Desnivel -"
android:textColor="#BBBBBB"
android:textSize="12sp"/>
<TextView
android:id="@+id/tvDetalleDesnivelNeg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="#F44336"
android:text="-380m"/>
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/tvDetalleReflexion"
<androidx.cardview.widget.CardView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/text_primary"
android:text="Cargando reflexión..."
android:layout_marginBottom="16dp"/>
app:cardBackgroundColor="#222222"
app:cardCornerRadius="8dp"
android:layout_marginBottom="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="12dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Perfil de Elevación"
android:textColor="@color/text_primary"
android:textStyle="bold"
android:layout_marginBottom="8dp"/>
<com.github.mikephil.charting.charts.LineChart
android:id="@+id/elevationChart"
android:layout_width="match_parent"
android:layout_height="150dp"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
<TextView
android:id="@+id/tvDetalleClima"
<androidx.cardview.widget.CardView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textColor="#FFEB3B"
android:text="Clima: --"
android:layout_marginBottom="24dp"/>
app:cardBackgroundColor="#222222"
app:cardCornerRadius="8dp"
android:layout_marginBottom="24dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="12dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Previsión del Tiempo (Próximos días)"
android:textColor="@color/text_primary"
android:textStyle="bold"
android:layout_marginBottom="8dp"/>
<TextView
android:id="@+id/tvDetalleClima"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textColor="#FFEB3B"
android:text="Cargando clima actual..."/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#444444"
android:layout_marginVertical="8dp"/>
<LinearLayout
android:id="@+id/layoutForecast"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="3"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
<Button
android:id="@+id/btnVerClima"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/btnVerMapa"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Ver Clima Actual"
android:layout_marginBottom="8dp"/>
android:text="Ver en Mapa / GPS"
android:backgroundTint="#1976D2"
android:layout_marginBottom="24dp"
app:icon="@android:drawable/ic_dialog_map"/>
<Button
android:id="@+id/btnVerAlbergues"
@ -105,7 +198,45 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Restaurantes"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"/>
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_marginBottom="24dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Historia del lugar"
android:textColor="@color/text_primary"
android:textStyle="bold"
android:textSize="18sp"
android:layout_marginBottom="8dp"/>
<TextView
android:id="@+id/tvDetalleHistoria"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#CCCCCC"
android:textSize="14sp"
android:layout_marginBottom="16dp"
android:text="Cargando historia..."/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Reflexión Espiritual"
android:textColor="@color/text_primary"
android:textStyle="bold"
android:textSize="18sp"
android:layout_marginBottom="8dp"/>
<TextView
android:id="@+id/tvDetalleReflexion"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#CCCCCC"
android:textSize="14sp"
android:fontStyle="italic"
android:layout_marginBottom="24dp"
android:text="Cargando reflexión..."/>
</LinearLayout>
</ScrollView>

View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/spiritual_black">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/spiritual_surface"
app:cardCornerRadius="24dp"
app:strokeWidth="1dp"
app:strokeColor="@color/spiritual_gold">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<TextView
android:id="@+id/tvDetalleNombre"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textColor="@color/white"
android:textSize="24sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvDetalleTipo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/label_category"
android:textColor="@color/spiritual_gold"
android:textSize="16sp"
android:textStyle="bold" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginVertical="16dp"
android:background="@color/spiritual_text_dim"
android:alpha="0.3" />
<TextView
android:id="@+id/tvDetalleDescripcion"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/msg_no_description"
android:textColor="@color/spiritual_text_bright"
android:textSize="16sp"
android:lineSpacingExtra="4dp" />
<LinearLayout
android:id="@+id/layoutExtras"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="vertical"
android:visibility="gone">
<TextView
android:id="@+id/tvDetalleCocina"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/msg_has_kitchen"
android:textColor="@color/accent_green"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:orientation="vertical">
<com.google.android.material.button.MaterialButton
android:id="@+id/btnLlamar"
style="@style/Widget.MaterialComponents.Button.Icon"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="@string/action_call"
app:icon="@android:drawable/ic_menu_call"
app:cornerRadius="16dp"
android:backgroundTint="@color/maritime_blue_deep"
android:textColor="@color/white"
android:layout_marginBottom="12dp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnComoLlegar"
style="@style/Widget.MaterialComponents.Button.Icon"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="@string/action_directions"
app:icon="@android:drawable/ic_menu_directions"
app:cornerRadius="16dp"
android:backgroundTint="@color/spiritual_surface"
app:strokeColor="@color/spiritual_gold"
app:strokeWidth="1dp"
android:textColor="@color/white" />
</LinearLayout>
</LinearLayout>
</ScrollView>

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".EtapasActivity">
<LinearLayout
android:id="@+id/headerLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="8dp"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Selecciona el Camino:"
android:textColor="@color/text_primary"
android:textSize="14sp"
android:layout_marginStart="8dp"/>
<Spinner
android:id="@+id/spinnerCaminos"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:background="@android:drawable/btn_dropdown" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Distancia máxima por etapa:"
android:textColor="@color/text_primary"
android:textSize="14sp"
android:layout_marginStart="8dp"/>
<Spinner
android:id="@+id/spinnerDistancia"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:background="@android:drawable/btn_dropdown" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerViewEtapas"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="@color/dark_background"
app:layout_constraintTop_toBottomOf="@id/headerLayout"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,28 +1,314 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
android:background="@color/spiritual_black"
android:fillViewport="true">
<Spinner
android:id="@+id/spinnerCaminos"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:background="@android:drawable/btn_dropdown"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerViewEtapas"
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="@color/dark_background"
app:layout_constraintTop_toBottomOf="@id/spinnerCaminos"
app:layout_constraintBottom_toBottomOf="parent" />
android:layout_height="wrap_content"
android:paddingBottom="40dp">
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- Fondo de Cabecera -->
<View
android:id="@+id/headerBackground"
android:layout_width="match_parent"
android:layout_height="220dp"
android:background="@color/maritime_blue_deep"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/txtGreeting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="56dp"
android:text="@string/welcome_message"
android:textColor="@color/white"
android:textSize="32sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- Tarjeta de Estado Flotante -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/statusCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="-50dp"
app:cardBackgroundColor="@color/spiritual_surface"
app:cardCornerRadius="24dp"
app:cardElevation="10dp"
app:layout_constraintTop_toBottomOf="@id/headerBackground"
app:strokeWidth="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="20dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/txtLocation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/location_sample"
android:textColor="@color/spiritual_gold"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:id="@+id/txtWeatherToday"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="@string/weather_sample"
android:textColor="@color/white"
android:textSize="18sp" />
</LinearLayout>
<View
android:layout_width="1dp"
android:layout_height="40dp"
android:layout_marginHorizontal="16dp"
android:background="@color/spiritual_text_dim" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/date_sample"
android:textColor="@color/spiritual_gold"
android:textSize="12sp"
android:textStyle="bold" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- SECCIÓN: RUTA (DESTACADA) -->
<TextView
android:id="@+id/labelRuta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="32dp"
android:text="@string/label_your_route"
android:letterSpacing="0.1"
android:textColor="@color/spiritual_text_dim"
android:textSize="12sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/statusCard" />
<com.google.android.material.card.MaterialCardView
android:id="@+id/btnMap"
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="12dp"
android:clickable="true"
android:focusable="true"
app:cardBackgroundColor="@color/spiritual_surface"
app:cardCornerRadius="24dp"
app:layout_constraintTop_toBottomOf="@id/labelRuta"
app:strokeColor="@color/maritime_blue_mary"
app:strokeWidth="1dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="24dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="@string/action_map"
android:textColor="@color/white"
android:textSize="22sp"
android:textStyle="bold" />
<ImageView
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_alignParentEnd="true"
android:alpha="0.1"
android:src="@android:drawable/ic_menu_mapmode"
app:tint="@color/white" />
</RelativeLayout>
</com.google.android.material.card.MaterialCardView>
<!-- SECCIÓN: SERVICIOS -->
<TextView
android:id="@+id/labelServicios"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="32dp"
android:text="@string/label_services"
android:letterSpacing="0.1"
android:textColor="@color/spiritual_text_dim"
android:textSize="12sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btnMap" />
<LinearLayout
android:id="@+id/layoutServicios"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="18dp"
android:layout_marginTop="12dp"
android:orientation="horizontal"
app:layout_constraintTop_toBottomOf="@id/labelServicios">
<com.google.android.material.card.MaterialCardView
android:id="@+id/btnSleep"
android:layout_width="0dp"
android:layout_height="110dp"
android:layout_margin="6dp"
android:layout_weight="1"
android:clickable="true"
android:focusable="true"
app:cardBackgroundColor="@color/spiritual_surface"
app:cardCornerRadius="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/action_sleep"
android:textColor="@color/spiritual_text_bright"
android:textStyle="bold" />
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/btnFood"
android:layout_width="0dp"
android:layout_height="110dp"
android:layout_margin="6dp"
android:layout_weight="1"
android:clickable="true"
android:focusable="true"
app:cardBackgroundColor="@color/spiritual_surface"
app:cardCornerRadius="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/action_food"
android:textColor="@color/spiritual_text_bright"
android:textStyle="bold" />
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
<!-- SECCIÓN: MI CAMINO -->
<TextView
android:id="@+id/labelPersonal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="24dp"
android:text="@string/label_personal"
android:letterSpacing="0.1"
android:textColor="@color/spiritual_text_dim"
android:textSize="12sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/layoutServicios" />
<GridLayout
android:id="@+id/gridPersonal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="18dp"
android:layout_marginTop="8dp"
android:columnCount="3"
app:layout_constraintTop_toBottomOf="@id/labelPersonal">
<com.google.android.material.card.MaterialCardView
android:id="@+id/btnDiary"
android:layout_width="0dp"
android:layout_height="90dp"
android:layout_columnWeight="1"
android:layout_margin="6dp"
android:clickable="true"
android:focusable="true"
app:cardBackgroundColor="@color/spiritual_surface"
app:cardCornerRadius="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/action_diary"
android:textColor="@color/spiritual_text_bright"
android:textSize="12sp" />
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/btnRegister"
android:layout_width="0dp"
android:layout_height="90dp"
android:layout_columnWeight="1"
android:layout_margin="6dp"
android:clickable="true"
android:focusable="true"
app:cardBackgroundColor="@color/spiritual_surface"
app:cardCornerRadius="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/action_seal_short"
android:textColor="@color/spiritual_text_bright"
android:textSize="12sp" />
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/btnTraining"
android:layout_width="0dp"
android:layout_height="90dp"
android:layout_columnWeight="1"
android:layout_margin="6dp"
android:clickable="true"
android:focusable="true"
app:cardBackgroundColor="@color/spiritual_surface"
app:cardCornerRadius="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/action_train_short"
android:textColor="@color/spiritual_text_bright"
android:textSize="12sp" />
</com.google.android.material.card.MaterialCardView>
</GridLayout>
<!-- FRASE FINAL -->
<TextView
android:id="@+id/txtQuote"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="48dp"
android:layout_marginHorizontal="48dp"
android:gravity="center"
android:text="@string/quote_spiritual"
android:textColor="@color/spiritual_gold"
android:textSize="15sp"
android:alpha="0.8"
android:lineSpacingExtra="6dp"
android:textStyle="italic"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/gridPersonal" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

View File

@ -3,5 +3,11 @@
"nombre": "Pulperia A Garnacha",
"latitud": 42.91390034545274,
"longitud": -8.011660067243549
},
{
"nombre": "Bar Manuel",
"latitud": 42.931718288986296,
"longitud":-8.127124619996351
}
]

View File

@ -1,3 +1,26 @@
<resources>
<string name="app_name">El Faro del Peregrino</string>
<string name="welcome_message">Buen Camino,\nTatiana</string>
<string name="label_your_route">TU RUTA</string>
<string name="label_services">SERVICIOS</string>
<string name="label_personal">MI CAMINO</string>
<string name="action_map">Mapa interactivo y\nEtapas del Camino</string>
<string name="action_sleep">Dónde\nDormir</string>
<string name="action_food">Dónde\nComer</string>
<string name="action_diary">Mi\nDiario</string>
<string name="action_register">Sellar\nCredencial</string>
<string name="action_training">Preparación</string>
<string name="action_train_short">Entrenar</string>
<string name="action_seal_short">Sellar</string>
<string name="weather_sample">19ºC · Cielo despejado</string>
<string name="date_sample">2 Mayo\nSábado</string>
<string name="location_sample">📍 Las Rozas de Madrid</string>
<string name="quote_spiritual">\"El camino me enseñó que el verdadero lujo es el que nos dedicamos a nosotros mismos.\"</string>
<string name="label_category">Categoría</string>
<string name="action_call">Llamar</string>
<string name="action_directions">Cómo llegar</string>
<string name="msg_no_description">Sin descripción disponible.</string>
<string name="msg_has_kitchen">🍳 Dispone de cocina</string>
<string name="msg_interest_place">Lugar de interés espiritual y arquitectónico en el Camino.</string>
<string name="msg_food_place">Disfruta de la gastronomía local en este establecimiento.</string>
</resources>

View File

@ -9,6 +9,7 @@ activity = "1.13.0"
constraintlayout = "2.2.1"
volley = "1.2.1"
glide = "4.16.0"
mpandroidchart = "v3.1.0"
[libraries]
junit = { group = "junit", name = "junit", version.ref = "junit" }
@ -21,6 +22,7 @@ constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayo
volley = { group = "com.android.volley", name = "volley", version.ref = "volley" }
glide = { group = "com.github.bumptech.glide", name = "glide", version.ref = "glide" }
glide-compiler = { group = "com.github.bumptech.glide", name = "compiler", version.ref = "glide" }
mpandroidchart = { group = "com.github.PhilJay", name = "MPAndroidChart", version.ref = "mpandroidchart" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }

View File

@ -19,6 +19,7 @@ dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}