Software

Supportare differenti dimensioni di schermo in android grazie ai Fragments

Nello sviluppo di applicazioni mobili diventa sempre più importante il supporto di schermi e dimensioni anche molto diverse a causa del diffondersi di modelli e tipologie di dispositivi sempre più disparati.
Per fortuna Android offre una soluzione veramente intelligente e semplice per aiutarci a sviluppare applicazioni che da un lato siano compatibili col maggior numero possibile di dispositivi ma che, dall’altro, si adattino al meglio agli schermi dei dispositivi in termini di usabilità e sfruttamento della superficie disponibile .

La soluzione sono i FRAGMENT.

In realtà i Fragment offrono altri grandi vantaggi come, ad esempio, poter scomporre le Activity in blocchi elementari (una sorta di “sub-activity”) replicabili e riutilizzabili in più layout o schermate applicative.
In questo articolo ci focalizzeremo su un semplicissimo esempio tramite il quale sviluppare un’Activity (che chiameremo MainActivity) in grado di presentarsi all’utente con due fragment affiancati nel caso lo schermo del dispositivo sia abbastanza grande da consentirlo (es. tablet), mentre negli altri casi gli stessi fragment vengono mostrati sequenzialmente (quasi come se fossero due Activity distinte).
L’ipotesi è quella di avere una listView di oggetti nel primo fragment (SxFragment) e il dettaglio dell’oggetto selezionato nel secondo fragment (DxFragment).

La figura seguente mostra l’esempio.

1) Layout
Predisponiamo due differenti layout per schermi piccoli e grandi. La stessa cosa, ad esempio, può essere fatta per Portrait/Landscape, con più fragmen, etc…

file: /res/layout-large/example_layout.xml

  1.  
  2. <?xml version="1.0" encoding="utf-8"?>
  3. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  4.     android:orientation="horizontal"
  5.     android:layout_width="match_parent"
  6.     android:layout_height="match_parent">
  7.    
  8.     <fragment android:name="com.example.fragments.SxFragment"
  9.             android:id="@+id/fgmList"
  10.             android:layout_weight="3"
  11.             android:layout_width="0dp"
  12.             android:layout_height="match_parent" />
  13.     <fragment android:name="com.example.fragments.DxFragment"
  14.             android:id="@+id/fgmDetail"
  15.             android:layout_weight="4"
  16.             android:layout_width="0dp"
  17.             android:layout_height="match_parent" />
  18.  
  19. </LinearLayout>
  20.  

file: /res/layout/example_layout.xml

  1.  
  2. <?xml version="1.0" encoding="utf-8"?>
  3. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  4.     android:id="@+id/fgmContainer"
  5.     android:layout_width="match_parent" android:layout_height="match_parent">
  6. </FrameLayout>
  7.  

Da notare che nel secondo layout non sono inclusi staticamente i Fragment e che è invece assegnato un id (fgmContainer) al contenitore che ci occorrerà per agganciare i fragment.

2) Activity principale

  1.  
  2. public class MainActivity extends Activity
  3.  

oppure nel caso di utilizzo della Android Support Library (retrocompatibilità con device che hanno versioni di android < 3.0):

  1.  
  2. public class MainActivity extends FragmentActivity
  3.  

Nel onCreate includiamo il layout e istanziamo dinamicamente il Fragment nel caso in cui siamo alle prese con uno schermo piccolo.

  1.  
  2. @Override
  3. protected void onCreate(Bundle savedInstanceState) {
  4.         super.onCreate(savedInstanceState);
  5.         setContentView(R.layout.fragment_contatti);
  6.  
  7.         // Check if using the layout version for small screen
  8.         if (findViewById(R.id.fgmContattiContainer) != null) {
  9.  
  10.                 // If restored from previous state do not add fragment
  11.                 if (savedInstanceState != null)
  12.                         return;
  13.        
  14.                 // Dynamically add list fragment
  15.                 SxFragment firstFragment = new SxFragment();
  16.  
  17.                 // Eventually pass parameters from intent
  18.                 firstFragment.setArguments(getIntent().getExtras());
  19.            
  20.                 // In case of using the android support library we must use the getSupportFragmentManager() method,
  21.                 // otherwise we use getFragmentManager() method.
  22.                 // The third parameter is an arbitrary TAG assigned to Fragment. We need to do that for being able
  23.                 // to find the corresponding fragment afterwards
  24.                 getSupportFragmentManager().beginTransaction()
  25.                     .add(R.id.fgmContainer, firstFragment, SxFragment.class.getName()).commit();
  26.         }
  27. }
  28.  

3) Fragment A (items list)
Nel fragment di sinistra, contenente la listView, assegnamo all’evento di selezione (OnItemClick) il compito di notificare la selezione tramite un metodo di callback (onItemSelected) all’attività principale.

  1.  
  2. public class SxFragment extends Fragment
  3. MainActivity parent; // Having the container activity can be useful to passing messages and parameters
  4. List<Item> items; // Objects in listView
  5.         @Override
  6.         public View onCreateView(LayoutInflater inflater, ViewGroup container,
  7.                         Bundle savedInstanceState) {
  8.                 super.onCreate(savedInstanceState);
  9.                
  10.                 View view = inflater.inflate(R.layout.my_list_layout,
  11.                                 container, false);
  12.  
  13.        
  14.                 parent = (MainActivity) getActivity();
  15.  
  16.                 // Get out listView and set onItemListClick listener in order to update the detail Fragment B
  17.                 myList = (ListView) view.findViewById(R.id.myList);
  18.                 myList.setOnItemClickListener(new OnItemClickListener() {
  19.  
  20.                 @Override
  21.                 public void onItemClick(AdapterView<?> arg0, View arg1,
  22.                                 int arg2, long arg3) {
  23.                                
  24.                         try {
  25.  
  26.                         // We can create an interface for calling activities (MainActivity) in order to
  27.                         // be sure to find the expected update method
  28.                                         OnItemListSelectedListener callback = (OnItemListSelectedListener)a;
  29.                                         Item c = items.get(arg2);
  30.  
  31.                                 // Pass new item selected to MainActivity
  32.                                         callback.onItemSelected(c);
  33.  
  34.                                 } catch (ClassCastException e) {
  35.                                 throw new ClassCastException(a.toString()
  36.                                  + " must implement OnItemListSelectedListener");
  37.                                 }
  38.                 }
  39.                 });
  40.         …
  41.         // MainActivity must implement this interface
  42.         public interface OnItemListSelectedListener {
  43.                 public void onItemSelected(Contatto c);
  44.         }
  45. }
  46.  

4) Activity principale
Aggiungo il metodo di selezione nella MainActivity. Chiaramente il metodo discrimina il caso in cui abbiamo entrambi i fragment da quello in cui occorra istanziare il secondo dinamicamente. Nel primo caso è sufficiente richiamare il metodo di update esposto dal fragment (doItemSelection), mentre nel secondo caso occorre effettuare una transizione dinamica tra i due Fragment. Il primo dei due, viene sostituito tramite “replace”, ma inserito nel Back Stack in modo che premendo il pulsante “Back” non termini l’activity ma venga semplicemente effettuata la transizione al contario e riappaia il primo Fragment.

  1.  
  2. public class MainActivity extends FragmentActivity
  3.                 implements SxFragment.OnItemListSelectedListener
  4.         …
  5.         Item selectedItem;
  6.         …
  7.         @Override
  8.         public void onItemSelected(Item item) {
  9.  
  10.                 // The user selected the headline of an article from the HeadlinesFragment
  11.                 // We verify if large screen layout is used or not by checking the presence
  12.                 // of the detail Fragment
  13.                 DxFragment itemDetailFrag = (DxFragment)
  14.                 getSupportFragmentManager().findFragmentById(R.id.fgmDetail);
  15.  
  16.                 // It’s better to maintain shared information in the MainActivity.
  17.                 // In this case we keep the item selected in the selectedItem class variable
  18.                 selectedItem = item;
  19.        
  20.                 if (itemDetailFrag != null) {
  21.                         // if detail fragment exists we simple need to update it
  22.                         itemDetailFrag.doItemSelection(selectedItem.getId().toString());
  23.                 } else {
  24.                         // Otherwise, swap fragments
  25.                         DxFragment newFragment = new DxFragment();
  26.  
  27.                         // Pass the necessary parameters (in this case the selectedItem)       
  28.                         Bundle args = new Bundle();
  29.                         args.putString(DxFragment.KEY_ITEM_SELECTED, selectedItem.getId().toString());
  30.                         newFragment.setArguments(args);
  31.        
  32.                         // Create transaction
  33.                         FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
  34.  
  35.                         // Replace the fragment and specify the transaction mode
  36.                         //note the arbitrary TAG passed in order to find the fragment afterwards
  37.                         //ID is not fixed because we are creating the fragment at runtime
  38.                         transaction.replace(R.id.fgmContainer, newFragment, DxFragment.class.getName());
  39.                         transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
  40.  
  41.                         //add the transaction to the back stack so the user can navigate back
  42.                         transaction.addToBackStack(null);
  43.  
  44.                         // Commit the transaction
  45.                         transaction.commit();
  46.                 }
  47.         }
  48. }
  49.  

5) Fragment B (item details)
Il Fragment B, infine, riceve come argomenti i parametri necessari alla sua inizializzazione o, se già inizializzato, espone i metodi necessari all’aggiornamento da parte della MainActivity. Nell’esempio semplicemente l’id dell’item selezionato viene inserito in una TextView.

  1.  
  2. public class DxFragment extends Fragment {
  3.  
  4.         public static String KEY_ITEM_SELECTED = "selectedItemKey";
  5.         …
  6.         TextView itemIdTxt;
  7.         String id;
  8.         MainActivity parent;
  9.         …
  10.         @Override
  11.         public View onCreateView(LayoutInflater inflater, ViewGroup container,
  12.                 Bundle savedInstanceState) {
  13.                 view = inflater.inflate(R.layout.my_detail_layout,
  14.                         container, false);
  15.                
  16.                 parent = (MainActivity) getActivity();
  17.        
  18.                 // Get textView from layout in order to show selected item’s id
  19.                 itemIdTxt = (TextView)view.findViewById(R.id.itemIdTxt);
  20.  
  21.                 // Get arguments containing the ID of selected item
  22.                 if(getArguments() != null)
  23.                         id = getArguments().getString(KEY_ITEM_SELECTED);
  24.        
  25.                 //initialize the item
  26.                 doItemSelection(id);
  27.                
  28.                 return view;
  29.         }
  30.        
  31.         //update method
  32.         public void doItemSelection(String id) {
  33.                 this.id = id;
  34.                 itemIdTxt.setText(id);
  35.         }
  36. }
  37.  

Nei prossimi articoli vedremo come effettuare la gestione di Menu e Actionbar nel caso di utilizzo dei Fragment.

Ciao e a presto
Federico

FireMonkey Mistery & Rad Studio XE2

Ieri consultando il mitico blog di Embarcadero ho scoperto che a breve uscirà la nuova versione di Rad Studio che come al solito conterrà la nuova versione dei prodotti Delphi, C++ Builder , Delphi Prism e RadPhp.
Le novità questa volta sono tantissime, come si evince dal post di DavidI http://blogs.embarcadero.com/davidi/2011/08/01/41062/ , ovviamente c’era da aspettarselo visto che da tempo è disponibile il nuovo compilatore a 64bit per Delphi e C++ Builder allora non ancora preso dall’entusiasmo mi guardo le nuove caratteristiche dell’ambiente pubblicate su tale post :

 

On the RAD Studio XE2 World Tour you will learn how to:

* Create GPU-powered FireMonkey applications that will keep your customers engaged
* Build 64-bit Delphi applications to take advantage of the latest hardware
* Create a single application and target both Windows and OS X
* Extend your multi-tier DataSnap applications with new mobile and cloud connectivity in RAD Cloud
* Connect any visual element to any type of data using LiveBindings™
* Modernize the look and feel of your Windows applications with VCL styles
* Create mobile-optimized web applications and standalone apps for iOS and Android devices using RadPHP

With Delphi and C++Builder in RAD Studio, you can write an app once and compile it for Windows and Mac. C++Builder apps can be compiled for Windows and Mac. Need apps for the web? RadPHP has you covered with a full visual web and PHP development solution. And it’s all done with the power and speed of component-based visual development that saves you time while still giving you full access to source code and hardware when you need it.

 

 

Incredile, in tutto silenzio sembre che con Delphi XE2 e C++ Builder XE2 sia arriavata anche la novità della piattaforma Mac, la cosa incredibile che Embarcadero ha registrato a tal proposito un nuovo marchio “FireMonkey” che dovrebbe essere un layer grafico cross-platform che consente alle applicazioni VCL di essere portate su più piattaforme anche trattandosi di codice nativo.
Un piccolo documento che ho trovato in merito a firemonkey http://www.andreanolanusse.com/en/a-little-bit-about-firemonkey-and-delphi-xe2/ , questo progetto sembra contenere tantissima tecnologia , ma non ho trovato nulla di ufficiale o dei demo in proposito, dalle vodi di corridoio sembra che permetta di :

  1. Gestire gli stili nelle VCL applications
  2. Permettere un facile porting verso la piattaforma Mac (avrà qualcosa in comune con le QT ??!! boh)
  3. Implementare la gestione della GPU cosa che credo sia gestita tramite la nuova tecnologia OpenCL

la curiosità è moltissima , il giorno 21 Settembre è prevista a milano una presentazione di Xe2 a cui ci si può iscrivere gratuitamente e ci sarò.

Aggiornamento del 40/08/2011 : ho trovato un articolo in merito a FireMonkey e XE2 all’indirizzo http://www.deltics.co.nz/blog/?p=735

a presto
ivan

Formazione in iFaber

Ciao a tutti!
Un breve articolo per documentare l’attività che con Ivan stiamo svolgendo da consulenti in iFaber.

Il progetto, nato in collaborazione con Elever srl ormai un anno fa, è finalizzato alla realizzazione di una portale web per la gestione e qualifica dei fornitori. Il portale è destinato sia ad uso interno (Unicredit) che per clienti terzi.

Il binomio tecnologico impiegato Zkoss+Oracle si è dimostrato all’avanguardia ed una scelta decisamente azzeccata (tempi di sviluppo brevissimi ma con affidabilità e prestazioni ottime). Altre tecnologie (come Hibernate e Axis) hanno fatto da corollario per la nascita di una web application veramente di grande spessore sia dal punto di vista funzionale che di concezione!

Presto saranno disponibili maggiori dettagli su questa e sulle altre attività di collaborazione nella sezione dedicata.

Questa settimana abbiamo tenuto, presso iFaber, un corso sull’applicazione dedicato prima di tutto ad introdurre nuove risorse (circa una dozzina), destinate ad ingrandire il team di sviluppo, alle tecnologie impiegate (in particolare Zkoss).
Il corso si è indirizzato poi a dare una panoramica delle caratteristiche peculiari dell’applicazione (tra cui dinamicità, configurabilità, internazionalizzazione, profilazione degli accessi…) scendendo nei dettagli tecnici implementativi necessari ad un primo contatto con il “dietro le quinte” di questo complesso portale.

Naturalmente ci siamo contraddistinti per il nostro stile ultra professionale (…) anche in questa circostanza!

Ecco qualche contributo dell’evento :-)

Ciao a tutti e “stay tuned!”

Problema debug Eclipse

Lavorando con Eclipse potrebbe capitare di incontrare una serie di problemi con la modalità di debug java.
In particolare, eclipse, sembra ignorare completamente i break points inseriti non interrompendo l’esecuzione del codice.

Sembra che il problema sia dovuto alla JRE utilizzata. In particolar modo dalla versione 1.6.14 fino alla 1.6.20.

Installando la versione 1.6.21 il debug torna a funzionare correttamente.

A presto

ShareTeam on Opera Versione 10.01 x64 Ubuntu 8.10

we have tried a lot of browser to use our ShareTeam Web Portal…. ok what is ShareTeam Portal? Is the Web module of our alfa version ERP solutiotion named ShareTeam.
Well, this web portal is not visible at the moment, we plan to start after first quarter of 2010, but we have also tried it and use it with a lot of numeber of Browser and Operating Systems….
ShareTeam WebPortal is developed using Java and ZKoss Framework, today i tried it with Opera 10.1 on a Ubuntu 8.10 x64 System, and is relly faster then a lot of other browser…

a screen shot : opera_10_1.png

so at the moment Opera looks like one of the faster browser for Ajax application that i tried until now. I don’t know about the new version of Chrome , that a lot of people said that is very fast. But at the moment Opera is more usable on different O/S …

bye
ivan

Scoprite cosa possiamo fare per il vostro business
I nostri linguaggi