====== 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?