android part 3 - interfejs użytkownika



Jednym z czterech podstawowych komponentów aplikacji w systemie Android jest aktywność (Activity). Aktywności są czymś w rodzaju warstwy prezentacji naszego programu. Zazwyczaj każdej aktywności przypisane jest osobne okno, które przy pomocy obiektów View i ViewGroup tworzy interfejs użytkownika. Kompleksowa aplikacja składa się ze zbioru aktywności, z którego każda aktywność ma swoją funkcję oraz może uruchamiać kolejne aktywności. Za każdym razem, kiedy uruchamiana jest nowa aktywność, poprzednia jest zatrzymywana. Szczegółowy cykl życia aktywności (Android Activity Lifecycle) opisany jest tutaj. Jeżeli kogoś interesują bardziej szczegółowe informacje o podstawach aplikacji w systemie Android, odsyłam tutaj, natomiast bardziej szczegółowe informacje o activities można znaleźć tutaj.

Jak już wspomniałem, interfejs użytkownika budowany jest z obiektów View oraz ViewGroup, które utworzone są w odpowiedniej hierarchii. Za wybór odpowiedniego widoku, przypisanego danej aktywności odpowiada metoda setContentView().
Istnieją dwa sposoby tworzenia layoutu:
  • poprzez plik XML
  • programowo
Generalnie zalecane jest tworzenie UI w pliku XML. Główną zaletą jest oddzielenie interfejsu użytkownika od kodu aplikacji, co pozwala zmieniać i dostosowywać go bez konieczności modyfikowania kodu źródłowego. Na przykład, można utworzyć XML z UI dla różnych orientacji ekranów lub dla różnych języków. Moim zdaniem brakuje tylko bezpośredniego dostępu do komponentów w kodzie. Każdy z nich należy odpowiednio wyszukać metodą findViewById() oraz rzutować na właściwy typ. Ilość kodu potrzebnego do wyszukania komponentów w XML nieznacznie jest mniejsza od kodu potrzebnego do stworzenia UI dynamicznie. W tym drugim przypadku odpada kod związany z tworzeniem pliku XML. Pytanie co jest lepsze? Co bardziej praktyczne? Wydaje mi się, że separacja layoutu od kodu bierze jednak górę nad podejściem programowym. Zawsze można oddelegować tworzenie interfejsu komuś innemu, a samemu zająć się tylko logiką programu. O sposobie tworzenia interfejsu użytkownika można poczytać bardziej szczegółowo tutaj.

View oraz ViewGroup
Obiekty typu View są to widgety, które mogą pojawić się na ekranie (label, button, textbox itd). Jeden lub więcej widoków można pogrupować w ViewGroup, który jest sam w sobie szczególnym rodzajem View. Oto przykłady ViewGroup:
  • LinearLayout
  • AbsoluteLayout
  • TableLayout
  • RelativeLayout
  • FrameLayout
  • ScrollView
O tym jak tworzyć poszczególne typy ViewGroup można poczytać tutaj oraz na stronie tutorialu Hello Views. Warto wspomnieć również o różnego typu narzędziach wspierających projektowanie interfejsu użytkownika. Do najbardziej popularnego należy zaliczyć darmowy edytor DroidDraw. O innych narzędziach można poczytać tutaj.

Poniżej przedstawiam kod realizujący prosty interfejs użytkownika, utworzony za pomocą pliku XML. Dwa widgety typu TextView oraz FrameLayout zawarte są w ViewGroup LinearLayout. Dotknięcie w polu FrameLayout powoduje rysowanie okręgu w przypadkowym kolorze. Na jednym polu tekstowym wyświetlone są współrzędne (x,y) dotkniętego punktu oraz na drugim licznik dotknięć.







>



Część kodu źródłowego ....
...
private TextView debug;
private TextView counter;
private FrameLayout circleContainer;
    
public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        circ = new Circle(this,startCircleX,startCircleY,25);
        setContentView(R.layout.main);
        debug = (TextView)this.findViewById(R.id.debugTxt);
        counter = (TextView)this.findViewById(R.id.counterTxt);
        circleContainer = (FrameLayout)this.findViewById(R.id.frameLay);
        circleContainer.addView(circ);
        circleContainer.setOnTouchListener(this);
        debug.setText("text1");
        counter.setText("text2");
}

oraz ten sam interfejs tworzony w sposób dynamiczny:
...
private TextView debug;
private TextView counter;
private FrameLayout circleContainer;
    
public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        LinearLayout outerContainer = new LinearLayout(this);
        circleContainer = new FrameLayout(this);
        circleContainer.setBackgroundColor(Color.BLACK);
        debug = new TextView(this);
        counter = new TextView(this);
         
        circ = new Circle(this,startCircleX,startCircleY,25);
        outerContainer.setOrientation(LinearLayout.VERTICAL);
        circleContainer.addView(circ);
        outerContainer.addView(debug);
        outerContainer.addView(counter);
        outerContainer.addView(circleContainer);
        circleContainer.setOnTouchListener(this);
        setContentView(outerContainer);
}

Rezultat przedstawiony na symulatorze:



oraz finalnie w urządzeniu:


Komentarze