====== Android Fragments ======
Els ''Fragment'' ens permetran disposar de diverses Activity alhora en la mateixa pantalla, a mode de pestanyes. Podrem navegar amb una ''NavigationBar'' que acostuma a tenir disposicions diferents segons la grandària i orientació de la pantalla, o del tipus de dispositiu.
Referències:
* [[Android]] a la pròpia wiki bytes.cat
* ...
{{tag> #Dam #DamMp08 #DamMp08Uf1 #DamMp08Uf01 #DamMp08Uf2 Android mobile java }}
{{ https://developer.android.com/static/images/guide/fragments/fragment-screen-sizes.png?500 }}
===== App amb fragments =====
App amb fragments:
- Crear app amb el //template// ''Bottom Navigation Activity''.
- Afegir un nou ''Fragment'' buit. Tria bé el nom (posarem d'exemple ''NewFragment'') Botó dret -> New -> Fragment -> Fragment (Blank)
- Afegir el nou ''Fragment'' a la navegació (via XML):res -> navigation -> mobile_navigation.xml
- Afegir el nou ''Fragment'' al menú de la ''NavigationBar'':res -> menu -> bottom_nav_menu.xml
- Anar a ''MainActivity.java'' i afegir ''R.id.navigation_XXX'' al ''onCreate'':AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_home, R.id.navigation_dashboard,
R.id.navigation_notifications, R.id.navigation_XXX)
.build();
- Posar una icona adequada pel nou fragment.
- La plantilla sol tenir un //padding-top// dins el //layout// del ''ActivityMain'' i sol deixar buida la part de dalt. Podeu mirar [[https://stackoverflow.com/questions/65777579/android-studio-bottom-navigation-activity-template-leaves-blank-area-on-the-to|aquest post]] per eliminar-la (simplement eliminant el //padding// o posar-lo a 0).
\\
===== ViewModel =====
Haureu vist que el ''NewFragment'' té només 1 sol arxiu, mentre que els ''Fragment'' creats a la plantilla (Home, Dashboard i Notifications) en tenen 2. Això és degut a que, acompanyant el ''Fragment'', també tenim un ''ViewModel''. **Aquest objecte ''ViewModel'' ens serveix per facilitar la persistència dels canvis en el GUI** sense haver d'utilitzar accés a fitxers o altres sistemes d'emmagatzemament.
No és necessari utilitzar el ''ViewModel'', tot i que **pot facilitar molta gestió, com per exemple quan girem (rotate) el mòbil de format //portrait// a //landscape//, moment en el qual es destrueixen les //views// i es tornen a crear de nou amb les noves mides i, per tant, perdem les dades del GUI**.
{{https://bytes.cat/_media/cicle_de_vida_activitat_android.png?200&direct&float|Cicle de vida d'una aplicació Android}}
\\
\\
Un [[https://developer.android.com/topic/libraries/architecture/viewmodel|ViewModel]] ens permetrà connectar la View amb el ViewModel mitjançant la sentència ''observe'', que prové d'un patró de disseny Observer. Aquest és el codi que ve per defecte a la plantilla:
homeViewModel.getText().observe(getViewLifecycleOwner(), textView::setText);
Per [[https://learn.microsoft.com/es-es/xamarin/xamarin-forms/enterprise-application-patterns/mvvm|aprendre mes del patró MVVM o Model-View-ViewModel]].
{{https://learn.microsoft.com/es-es/xamarin/xamarin-forms/enterprise-application-patterns/mvvm-images/mvvm.png}}
Afegeix un ''Button'' i un ''TextView'' al ''HomeFragment''. Hauriem de tenir 2 ''TextView'', un AMB ViewModel (el què ja existia) i un sense.
Implementa aquesta funcionalitat simple: quan premem el botó, canvia el text dels dos ''TextView'', però cal fer-ho diferent en l'un i l'altre:
* En el ''TextView'' AMB ''ViewModel'' cal modificar el ''ViewModel''.
* En el ''TextView'' SENSE ''ViewModel'' el modifiquem directament.
Algo així:
homeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Modifiquem objecte sense ViewModel directament
TextView directTextView = root.findViewById(R.id.directTextView);
directTextView.setText("[NOT ViewModel] canvi de text");
// Modifiquem contingut ViewModel (es reflaxarà a la View)
homeViewModel.setText("[WITH ViewModel] canvi de text");
}
});
Ara posa l'app en marxa, habilita el //autorotate// de l'emulador i observa què passa.
Com expliques aquest comportament?