Skip to content

Design Login #7

Description

@GVQ-uwu

Excelente decisión, Génesis 💪✨
Vas a separar el login del menú principal, lo que le da a tu app una estructura profesional como cualquier aplicación real.

El flujo quedará así:

🔐 LoginActivity  →  🏠 MainActivity (con el Drawer y contenido)

🎯 OBJETIVO

  1. Crear una pantalla de inicio de sesión simple (LoginActivity)

  2. Si el login es correcto → abrir MainActivity

  3. Si no → mostrar error o quedarse en login

  4. Guardar sesión (opcional) con SharedPreferences


🧩 1️⃣ Crea el nuevo Activity

En Android Studio:
➡️ app/java/com.example.api_calendar/ui/
Haz clic derecho → New → Activity → Empty Activity
📛 Nombre: LoginActivity
✅ Marca Generate Layout File


📄 2️⃣ activity_login.xml

Reemplaza el layout por este diseño limpio y Material (tema oscuro compatible):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:padding="32dp"
    android:gravity="center"
    android:background="@color/md_black"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
&lt;TextView
    android:text="API Calendar"
    android:textColor="@color/md_on"
    android:textStyle="bold"
    android:textSize="28sp"
    android:layout_marginBottom="24dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" /&gt;

&lt;com.google.android.material.textfield.TextInputLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Correo electrónico"
    app:boxBackgroundMode="filled"
    app:boxBackgroundColor="@color/md_surface"&gt;

    &lt;com.google.android.material.textfield.TextInputEditText
        android:id="@+id/etEmail"
        android:inputType="textEmailAddress"
        android:textColor="@color/md_on"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" /&gt;
&lt;/com.google.android.material.textfield.TextInputLayout&gt;

&lt;com.google.android.material.textfield.TextInputLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Contraseña"
    android:layout_marginTop="16dp"
    app:boxBackgroundMode="filled"
    app:boxBackgroundColor="@color/md_surface"&gt;

    &lt;com.google.android.material.textfield.TextInputEditText
        android:id="@+id/etPassword"
        android:inputType="textPassword"
        android:textColor="@color/md_on"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" /&gt;
&lt;/com.google.android.material.textfield.TextInputLayout&gt;

&lt;com.google.android.material.button.MaterialButton
    android:id="@+id/btnLogin"
    android:text="Iniciar sesión"
    style="?attr/materialButtonOutlinedStyle"
    android:textAllCaps="false"
    android:textColor="@color/md_on"
    android:layout_marginTop="24dp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:cornerRadius="12dp"
    app:backgroundTint="@color/md_surface" /&gt;

</LinearLayout>


📘 3️⃣ LoginActivity.kt

📄 app/src/main/java/com/example/api_calendar/ui/LoginActivity.kt

package com.example.api_calendar.ui

import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.api_calendar.databinding.ActivityLoginBinding

class LoginActivity : AppCompatActivity() {

private lateinit var binding: ActivityLoginBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityLoginBinding.inflate(layoutInflater)
    setContentView(binding.root)

    // Botón de inicio de sesión
    binding.btnLogin.setOnClickListener {
        val email = binding.etEmail.text.toString()
        val password = binding.etPassword.text.toString()

        if (email.isEmpty() || password.isEmpty()) {
            Toast.makeText(this, "Por favor completa todos los campos", Toast.LENGTH_SHORT).show()
        } else if (email == "admin@duoc.cl" &amp;&amp; password == "1234") {
            // Simula un login correcto
            Toast.makeText(this, "Inicio de sesión exitoso", Toast.LENGTH_SHORT).show()

            // Navegar al MainActivity
            val intent = Intent(this, MainActivity::class.java)
            startActivity(intent)
            finish() // cerrar la pantalla de login
        } else {
            Toast.makeText(this, "Credenciales incorrectas", Toast.LENGTH_SHORT).show()
        }
    }
}

}


🧱 4️⃣ Configura el arranque inicial

Abre tu archivo AndroidManifest.xml
y mueve el intent-filter que marca la pantalla inicial (MAIN + LAUNCHER)
desde MainActivity hacia LoginActivity 👇

<activity android:name=".ui.MainActivity" />
<activity
    android:name=".ui.LoginActivity"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

✅ Esto hace que tu aplicación inicie en el login.


⚙️ 5️⃣ (Opcional) Guardar sesión con SharedPreferences

Para no tener que loguearte cada vez:

Dentro de LoginActivity (luego del login exitoso):

val prefs = getSharedPreferences("user_session", MODE_PRIVATE)
prefs.edit().putBoolean("isLogged", true).apply()

Y en el onCreate() de LoginActivity agrega:

val prefs = getSharedPreferences("user_session", MODE_PRIVATE)
if (prefs.getBoolean("isLogged", false)) {
    startActivity(Intent(this, MainActivity::class.java))
    finish()
}

✨ Resultado final

Pantalla Función
🔐 LoginActivity Muestra formulario de inicio de sesión
🏠 MainActivity Contiene el menú lateral, saludo, resumen y calendario
🔁 Flujo App inicia en login → valida → entra a panel principal

Excelente, Génesis 🙌✨
Esa es la parte clave del flujo de sesión completo, para que la app:

1️⃣ muestre el login cuando abres la app (si aún no has iniciado sesión)
2️⃣ guarde el estado de sesión (para no volver a loguearte cada vez)
3️⃣ redirija automáticamente al MainActivity después de un login exitoso
4️⃣ muestre de nuevo el login cuando cierres sesión.

Vamos paso a paso 👇


🧩 PASO 1 — Guardar el estado de sesión

En el LoginActivity, después de un login exitoso (cuando abres el Main),
guarda una variable llamada isLogged en las preferencias del usuario (SharedPreferences).

📄 LoginActivity.kt

package com.example.api_calendar.ui

import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.api_calendar.databinding.ActivityLoginBinding

class LoginActivity : AppCompatActivity() {

private lateinit var binding: ActivityLoginBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityLoginBinding.inflate(layoutInflater)
    setContentView(binding.root)

    // 🔹 Verifica si ya hay sesión activa
    val prefs = getSharedPreferences("user_session", MODE_PRIVATE)
    val isLogged = prefs.getBoolean("isLogged", false)
    if (isLogged) {
        startActivity(Intent(this, MainActivity::class.java))
        finish()
        return
    }

    // 🔹 Botón de login
    binding.btnLogin.setOnClickListener {
        val email = binding.etEmail.text.toString()
        val password = binding.etPassword.text.toString()

        if (email.isEmpty() || password.isEmpty()) {
            Toast.makeText(this, "Por favor completa todos los campos", Toast.LENGTH_SHORT).show()
        } else if (email == "admin@duoc.cl" &amp;&amp; password == "1234") {
            // ✅ Login correcto
            Toast.makeText(this, "Inicio de sesión exitoso", Toast.LENGTH_SHORT).show()

            // Guardar sesión activa
            prefs.edit().putBoolean("isLogged", true).apply()

            // Ir al MainActivity
            startActivity(Intent(this, MainActivity::class.java))
            finish()
        } else {
            Toast.makeText(this, "Credenciales incorrectas", Toast.LENGTH_SHORT).show()
        }
    }
}

}


🧠 ¿Qué hace esto?

  • Si ya hay sesión (isLogged == true), no muestra el login, salta directo al Main.

  • Si no hay sesión, muestra el formulario.

  • Cuando el login es exitoso, guarda el estado y redirige al Main.


🧱 PASO 2 — Cerrar sesión (logout) desde el menú del MainActivity

Agrega un ítem nuevo en tu menú lateral (menu_main_drawer.xml):

📄 res/menu/menu_main_drawer.xml

<item
    android:id="@+id/nav_logout"
    android:title="Cerrar sesión"
    android:icon="@drawable/ic_logout_24"/>

(usa cualquier ícono, por ejemplo uno de Material Icons → “logout”)


⚙️ PASO 3 — Implementar el “Cerrar sesión” en MainActivity

📄 MainActivity.kt
Agrega esta parte dentro del setNavigationItemSelectedListener:

binding.navigationView.setNavigationItemSelectedListener { item ->
    when (item.itemId) {
        R.id.nav_home -> {}
        R.id.nav_calendar -> startActivity(Intent(this, CalendarActivity::class.java))
        R.id.nav_list -> startActivity(Intent(this, ListActivity::class.java))
        R.id.nav_notifications -> startActivity(Intent(this, NotificationsActivity::class.java))
        R.id.nav_settings -> startActivity(Intent(this, SettingsActivity::class.java))
        R.id.nav_logout -> {
            // 🔹 Cerrar sesión
            val prefs = getSharedPreferences("user_session", MODE_PRIVATE)
            prefs.edit().putBoolean("isLogged", false).apply()
        // Volver al LoginActivity
        val intent = Intent(this, LoginActivity::class.java)
        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
        startActivity(intent)
        finish()
    }
}
binding.drawerLayout.closeDrawer(GravityCompat.START)
true

}


🪄 PASO 4 — Ajustar el AndroidManifest.xml

Asegúrate que la app empiece en el LoginActivity:

📄 AndroidManifest.xml

<activity android:name=".ui.MainActivity" />
<activity
    android:name=".ui.LoginActivity"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

✅ Resultado final

Estado Pantalla que se muestra
🔒 No has iniciado sesión LoginActivity
🔓 Login correcto Te redirige al MainActivity
🔁 Cerrar sesión desde el menú Borra sesión y vuelve al login

🌟 BONUS (Opcional)

Si quieres personalizar el saludo en el MainActivity con el correo que inició sesión:

  • Guarda el correo al iniciar sesión:

    prefs.edit().putString("email", email).apply()
    
  • Y muéstralo en el Main:

    val prefs = getSharedPreferences("user_session", MODE_PRIVATE)
    val userEmail = prefs.getString("email", "Estudiante")
    binding.tvGreeting.text = "Hola, $userEmail 👋"
    

¿Quieres que te lo deje listo también con inicio de sesión mediante Google (Google Sign-In) en vez de correo fijo?
Así podrías entrar con tu cuenta @gmail.com y que se sincronice directamente con el Google Calendar real.

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions