MójDroid.pl

#18 Twórz aplikacje na Androida z Mojdroid.pl – Dialogi

2012-10-30
|
Damian P.

Dialogi to małe okna w systemie, które proszą użytkownika o wybranie jednej z możliwości lub wprowadzenie dodatkowych danych. W przeciwieństwie do poznanych już elementów, Dialogi nie zajmują całego obszaru roboczego a tylko jego część. Dziś poznamy zasadę ich działania, tworzenia jak i obsługi.

1. Dialog

Te małe okna występują zazwyczaj przed wykonaniem jakiejś ważniej czynności w aplikacji, na przykład przed usunięciem dużej ilości danych. Wtedy proszeni jesteśmy o potwierdzenie swojej decyzji ostatni raz, po czym odbywa się wyznaczona w aplikacji akcja. W skrócie już o nich mówiłem, przedstawiając główne elementy interfejsu. Jak pewnie się spodziewacie, podstawową klasą to tworzenia tych elementów jest Dialog. Nie powinniśmy jednak odwoływać się do niej bezpośrednio, a poprzez wykorzystanie jednej z subklas:
  • AlertDialog - prosty komunikat, który może zwierać do trzech przycisków, prosty komunikat, tytuł i własny layout.
  • Picker - czyli dialog z zdefiniowanymi już elementami, które wykorzystujemy w jakimś z góry wyznaczonym celu (np DatePicker - do wybrania daty).
Jednak sam Dialog od początku tak nie wyglądał. Wraz z prowadzeniem Androida 4.0 zasada jego działania lekko się zmieniła, ale zgodnie z całą serią poradników - tych aktualizacji dziś omawiać nie będę. SDK Ice Cream Sandwicha wprowadza mnóstwo zmian, ale aby w pełni zrozumieć ich działanie potrzebujemy poznać podstawy z wcześniejszych wersji systemu.

2. Tworzenie Dialogu

Oficjalna dokumentacja Androida podpowiada, aby przy tworzeniu komunikatów używać DialogFragment-ów. Te jednak nie są wymagane, więc nie musimy zaprzęgać do pracy kolejnych procesów aby wyświetlić prosty komunikat. Ja pominę te elementy, przedstawiając jedynie to co jest potrzebne. My nasz Dialog opierać będziemy oczywiście na tej pierwszej subklasie, AlertDialogu. Jak pisałem, możemy do niego dodać przyciski, własne layouty czy opisy bez większych problemów. Podstawą do jego budowy jest jeden z elementów klasy AlertDialog - Builder. Oczywiście, aby móc skorzystać z jego możliwości potrzebujemy łącznika z aplikacją - Contextu. Kolejne elementy nie są już wymagane i ich wybór zależy od tego, co chcemy w Dialogu użyć. I tak aby dodać wiadomość do okienka należy wywołać metodę setMessage na stworzonym wcześniej Builderze. Aby dodać przycisk - wybieramy funckję setPositiveButton, setNegativeButton lub setNeutralButton (obsługujemy je tak samo, różnią się one jedynie pozycją). Wszystkie możliwości zobaczycie podczas tworzenia każdego z elementów oraz w samej dokumentacji Androida. Ostatnim krokiem jest stworzenie Dialogu i wyświetlenie go. Po dodaniu wszystkich elementów i opisaniu Listernerów (np. reakcji na kliknięcie) należy na Builderze kolejno wywołać funkcje Create i Show. Przykładowy kod Dialogu zobaczycie poniżej. Niestety, tym razem nie mam możliwości zbudowania swojego kodu i dodania go do aplikacji, więc skorzystam z tego co oferuje nam dokumentacja na android.com. Te same elementy dodam do aplikacji wtedy, gdy będę miał dostęp do swojego sprzętu. *Przepraszam za takie zamieszanie, ale tak wyszło... A kod z pewnością działa, tego możecie być pewni. Kod przykładowego Dialogu:
public class FireMissilesDialogFragment extends DialogFragment {
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Używamy Buildera do stworzenia Dialogu
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setMessage("Fire missles?")
               .setPositiveButton("Fire", new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // Fire
                   }
               })
               .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // Cancel
                   }
               });
        // Tworzymy AlertDialog i wyświetlamy go
        return builder.create();
    }
}
Efekt? Widoczny poniżej: W przykładzie użyto kilku z możliwych elementów, i jak pisałem - resztę podpowie wam Eclipse i dokumentacja systemu. Przykłady wykorzystania:

Dialog z naszym własnym layoutem

Dialog z listą (setItems, który wymaga tablicę stringów)

Dialog z listą wyboru (setMultiChoiceItems() - checkboxy, setSingleChoiceItems() - radio buttony)

3. Reakcja na kliknięcia

Ta część opisana została już wyżej, ale chcę upewnić was w sposobie jej działania. Napisałem, że przyciski setPositiveButton, setNegativeButton i setNeutralButton prawie niczym się od siebie nie różnią. I to prawda - spójrzcie na powyższe przykłady. Można zauważyć, że potwierdzenie (setPositiveButton) zawsze znajduje się po prawej stronie, zaprzeczenie (setNegativeButton) po lewej, a niewidoczny powyżej neutralny wybór (setNeutralButton) - będzie obecny na środku. Oczywiście każdy z przycisków może mieć własny tekst i nie musi być to tylko "Anuluj" i "Potwierdź". Obsługa przycisku jest bardzo prosta. Tworząc go kolejno definiujemy tekst, który będzie na nim widoczny, oraz wskazujemy na nasz Listener z głównej klasy Dialog. Jak wiecie, ten możemy stworzyć od razu przy definiowaniu przycisku. Reszta należy do was - wewnątrz onClick() dodajemy swoją logikę. * Aby zamknąć Dialog zostawcie pustą funkcję onClick

4. Własny layout w Dialogu

Ciekawa opcja w tym komponencie. Może zdarzyć się, że podstawowe możliwości AlertDialogów nam nie wystarczą, dlatego system oferuje możliwość dodatnia własnych elementów wewnątrz okienka. Należy jedynie pamiętać o bardzo małych rozmiarach tego elementu - może zdarzyć się, że coś się nie zmieści... * Dialog posiada opcję wyświetlania na całym obszarze roboczym. Aby dodać własny Layout należy na Builderze wywołać metodę setView(), przekazując jako argument jedynie Inflantera z identyfikatorem naszego szablonu, lub setContentView() wraz z ID naszego XMLa. Czym obie metody się różnią? SetView nasz layout umieści w środku Dialogu, pod tytułem a nad przyciskami (więc możemy ich używać). SetContentView wykorzysta cały dostępny obszar. Jak wtedy obsługiwać dodane elementy? W przypadku setContentView bezpośrednio korzystając z findViewById, w przypadku setContentView - po wykonaniu Builder.Create(). setContentView, przykład:
(...)
alertDialog.setContentView(R.layout.layout);
TextView text = (TextView) findViewById(R.id.text);
text.setText("Witaj!");
(...)
setView, przykład:
// Nasze zdefiniowane Buildery i AlertDialogi
AlertDialog.Builder builder;
AlertDialog alertDialog;

(...)

//Context mContext = getApplicationContext();
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);
// lub:
// Inflater.from(this)/Inflater.from(mContext) 
// mContext.getSystemService/getSystemService

// Nasz layout
View layout = inflater.inflate(R.layout.custom_dialog,
        (ViewGroup) findViewById(R.id.layout_root));

// I elementy w nim
TextView text = (TextView) layout.findViewById(R.id.text);
text.setText("Witaj!");
ImageView image = (ImageView) layout.findViewById(R.id.image);
image.setImageResource(R.drawable.android);

// Budowanie i pokazywanie
builder = new AlertDialog.Builder(mContext);
builder.setView(layout);
alertDialog = builder.create();