fragmentos - tec · 2020. 3. 25. · proyectos de desarrollo para dispositivos móviles fragmentos...
TRANSCRIPT
Proyectos de desarrollo para dispositivos móviles
Fragmentos Android
Fragmento❖ Un fragmento es una parte de una actividad con ciclo de
vida propio.
❖ Recibe sus propios eventos.
❖ Se puede agregar o quitar mientras la actividad se está ejecutando.
❖ Se puede decir que es una "subActividad".
❖ Permiten reusar código.
❖ Un fragmento no es una actividad.
Una actividad, tres fragmentos
Actividad
FragmentoA
FragmentoB
FragmentoC
4 vistas, 4 controladores
activos al mismo tiempo.
4 xml, 4 .kt
Diferentes pantallas❖ Los fragmentos permiten configurar la GUI dependiendo de la
pantalla en que corre la app.
Ciclo de vida del fragmento
❖ Normalmente sobrescribimos los métodos del ciclo de vida:➡ onCreate
➡ onCreateView
➡ onPause
Ejercicio
❖ Crea un proyecto nuevo:
PruebaFragmentos
❖ Selecciona el template:
Bottom Navigation Activity
❖ Nombre de la actividad inicial:
Principal
Revisa el proyectoRevisa el código y determina:
‣ Cómo se agrega la barra de navegación.
‣ Cómo se configuran los botones de la barra de navegación.
‣ Cómo responder a los eventos, de los botones, de la barra de navegación.
‣ Corre la app y observa el comportamiento.
‣ Agrega un nuevo botón.
Configurando❖ Borra los fragmentos y sus vistas, creados por el Wizard.
❖ Agrega el listener en Principal.navView.setOnNavigationItemSelectedListener { item -> Boolean when (item.itemId) { R.id.navigation_home -> println("Home") R.id.navigation_dashboard -> println("Dashboard") R.id.navigation_notifications -> println("Notifications") R.id.navigation_otro -> println("Otro") else -> println("Desconocido") }
true }
Creando fragmentos❖ Crea un fragmento para la
opción de Home.❖ Observa que se crea un
archivo HomeFrag.kt y otro fragment_home.xml
❖ Crea la interfaz de usuario para este fragmento.
Crea fragmentos para las otras opciones:
DashboardFrag, NotificationsFrag, OtroFrag.
Agregando fragmentosLa forma más sencilla de agregar un fragmento es con un componente <fragment>, pero también es la menos flexible.
Borra el contenedor que agregó el wizard y añade un Fragment de prueba.
De esta manera puedes agregar fragmentos 'estáticos', es decir se comportan como cualquier otro componente.
Agregando fragmentos de manera dinámica
Los fragmentos se pueden manipular de manera dinámica.
Borra el Fragment de prueba y agrega un FrameLayout. (id: contenedorFragmentos)
Agregamos un 'contenedor' a la interfaz y con programación podemos poner/quitar fragmentos.
Agregar un fragmento de manera dinámica
fragHome = FragHome()
supportFragmentManager.beginTransaction() .replace(R.id.contenedorFragmentos, fragHome) .commit()
Opciones para agregar fragmentosfragHome = FragHome()
supportFragmentManager.beginTransaction() .replace(R.id.contenedorFragmentos, fragHome) .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) .addToBackStack(fragHome.toString()) .commit()
Ahora te toca a tiCrea los otros fragmentos para completar la app. Muestra el correspondiente cada vez que el usuario selecciona un botón diferente en la barra de navegación.
Práctica
❖ Implementamos una app que muestre un índice con una lista de materias.
❖ Al oprimir una materia se carga la información detallada.
❖ En el teléfono hay dos actividades.
❖ En la tableta, hay una sola mostrando la lista y los detalles.
DiseñoMaestroActiv DetalleActiv
<fragment>MateriaDetalleFrag
- indice+ setIndice
Creando el proyecto
❖ Crea el proyecto MateriasFragmentos.
❖ La actividad principal es MaestroActiv. Empty Activity.
❖ SDK mínimo 19.❖ Crea una segunda actividad
DetalleActiv. Empty Activity.
Navegación❖ Agrega un botón de prueba en la actividad principal.
❖ Al hacer click al botón, inicia la segunda actividad por medio de un Intent.
❖ Crea un emulador de tablet y prueba la app tanto en teléfono como en tableta.
Agregando un fragmento
❖ Agrega un fragmento en blanco al proyecto.
❖ Nombre: MateriaDetalleFrag.❖ Pide que se cree el archivo
XML.
Layout del fragmentofragment_materia_detalle.xml
1. Cambia el Layout a ConstraintLayout
2. Agrega/Modifica el TextView (tvTitulo) como título que contendrá el nombre de la materia que se despliega.
3. Agrega un TextView (tvDetalle). Ocupa todo el espacio inferior disponible para desplegar la información de la materia.
Agregando un fragmentoactivity_detalle.xml
❖ Utiliza un componente fragment para agregar el fragmento al layout de detalle.
DetalleActiv<fragment>
id: fragMateriaDetalle
DiseñoMaestroActiv
findF
ragm
entB
yId
MateriaDetalleFrag- indice
+ setIndice()
Comunicándonos con el Fragmento❖ Crea la clase Materia que servirá para proporcionar los
datos que queremos desplegar.❖ https://gist.github.com/rmroman/5d74249cf8f30c35a404bfc5fe8b33e7
❖ Ahora, la actividad (DetalleActiv) necesita indicarle al fragmento cuál materia desplegar.
❖ Agrega a MateriaDetalleFrag una variable de instancia indice de tipo int y el método set.
FragmentManager❖ Para comunicarse con el fragmento, la actividad
(DetalleActiv) requiere una referencia al fragmento. Ya la tiene de manera automática, es el id que le asignamos al contenedor <fragment>: fragMateriaDetalle
❖ Si ya tenemos la referencia, podemos enviar el indice que se quiere mostrar usando el método setIndice. Esto dentro de la clase DetalleActiv.
fragmento.indice = 0
Cambiando propiedades del fragmento❖ En el método onStart() del fragmento, asignamos
valores.
override fun onStart() { super.onStart() if (view != null) { val materia = Materia.arrMaterias[indice] tvTitulo.text = materia.nombre tvDetalle.text = materia.descripcion } }
Implementa la lista de materias❖ Crea un nuevo fragmento sin layout, llámalo ListaMateriasFrag.
❖ Cambia la superclase y el método onCreateView.
class FragListaMaterias : ListFragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? {
val vista = super.onCreateView(inflater, container, savedInstanceState)
return vista } }
MaestroActiv
<fragment> ListaMateriasFrag
Datos para la lista❖ En el método onCreateView, del fragmento, vamos a crear
el adaptador de la lista.override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? {
val vista = super.onCreateView(inflater, container, savedInstanceState)
var materias = Array<String>(Materia.arrMaterias.size, {i -> ""} ) for (i in 0..Materia.arrMaterias.size-1) { materias[i] = Materia.arrMaterias[i].nombre }
val adaptador = ArrayAdapter<String>(inflater.context, android.R.layout.simple_list_item_1, materias) listAdapter = adaptador
return vista }
var materias = Array<String>(Materia.arrMaterias.size) { i -> Materia.arrMaterias[i].nombre }
DetalleActiv<fragment>
fragMateriaDetalle
MateriaDetalleFrag- indice
+ setIndice
DiseñoMaestroActiv
<fragment> ListaMateriasFrag
findF
ragm
entB
yId
Agrega la lista a la actividad principal❖ En activity_maestro.xml/activity_main.xml agregamos un
componente fragment de tipo ListaMateriasFrag.
❖ Corre la app y observa cómo despliega la lista de materias.
Agrega la lista a la actividad principal❖ Solo falta detectar el click sobre la materia y llamar a la de detalle con el
dato correspondiente.
❖ Este click lo detecta el fragmento 1⃣, lee el índice correspondiente y lo manda a la actividad 2⃣, para qué, a su vez, lo reenvíe a la actividad de Detalle 3⃣. Después la actividad de detalle lo manda al fragmento detalle 4⃣ para mostrar el detalle de la materia 5⃣. 😧
DetalleActiv<fragment>
fragMateriaDetalle
MateriaDetalleFrag- indice
+ setIndice
DiseñoMaestroActiv
<fragment> ListaMateriasFrag
indice
click
indice
Interfaces❖ Declara una interface en el fragmento de la lista.// Interface companion object { interface ListenerLista { fun itemClicked(indice: Int) } } // Variable de instancia en el fragmento var listener: ListenerLista? = null
❖ En el método onAttach, guarda el contexto (actividad)override fun onAttach(context: Context?) { super.onAttach(context) if (context is ListenerLista) { listener = context as ListenerLista } else { // Error } }
Interfaces
❖ En el fragmento, sobrescribe el método que recibe el evento.
override fun onListItemClick(l: ListView?, v: View?, position: Int, id: Long) {
listener?.itemClicked(position) }
¿Cuál es la diferencia?Respuesta
Implementando la interface❖ Implementa la interface en la actividad principal y
sobrescribe el método itemClicked.
class MaestroActiv : AppCompatActivity(), FragListaMaterias.Companion.ListenerLista { ...
override fun itemClicked(indice: Int) { val intDetalle = Intent(this, DetalleActiv::class.java) intDetalle.putExtra("POSICION", indice) startActivity(intDetalle) } }
Terminando❖ Finalmente, en la actividad de Detalle, lee el valor que se
pasó en el Intent y envíalo al fragmento (fragMateriaDetalle).
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_detalle)
val indice = intent.getIntExtra("POSICION", 0) val fragmento = fragMateriaDetalle as MateriaDetalleFrag fragmento.indice = indice }