Skip to content

Technik Blog

Programmieren | Arduino | ESP32 | MicroPython | Python | Raspberry Pi | Raspberry Pi Pico

Menu
  • Smarthome
  • Arduino
  • ESP32 & Co.
  • Raspberry Pi & Pico
  • Solo Mining
  • Über mich
  • Deutsch
  • English
Menu

Android, PopUpDialog mit auswählbaren ListItems

Posted on 4. Oktober 20152. Mai 2023 by Stefan Draeger

In diesem Tutorial möchte ich erklären wie ich ein benutzerdefiniertes PopupDialog für eine Activity erstelle.

TagCludDialog, zum wählen von Tags für eine Android Anwendung

Für mein aktuelles Projekt benötige ich unter anderem diverse Dialoge welche es nicht standardmäßig von Android gibt zbsp:.

  • DateTimePickerDialog (zur Auswahl eines Zeitstempels)
  • TagCloudDialog (zum setzen von Tags)

Hier möchte ich beschreiben wie ich mein TagCloudDialog erstellt habe, welches dazu dient einen oder mehrere Tags aus einer Liste (ListView) zu wählen welche nach dem Bestätigen des Dialoges auf der Activity dargestellt werden.
Grundsätzlich habe ich mich an dem bestehenden Beispiel zur DialogFragment API von der Android-Hilfe gehalten.

Inhaltsverzeichnis

  • Die Klasse TagCloudDialog
  • Das Layout „tagclouddialog.xml“
  • Befüllen der Liste mit Hilfe des ArrayAdapters
    • Die Klasse „TagCloudListAdapter“
    • Zuweisen der View für die Darstellung der CheckboxItems
    • Registrieren des Adapters an der ListView
  • Interaktion zwischen dem Dialog und der Activity
  • Event für die Schaltfläche „OK“
  • Event für die Schaltfläche „Abbrechen“

Die Klasse TagCloudDialog

Die Klasse TagCloudDialog wird später unser Dialog darstellen.

import android.app.DialogFragment;


public class TagCloudDialog extends DialogFragment{
    
}

Es erweitert erstmal die Klasse DialogFragment welche die Grundfunktionalitäten eines PopupDialoges mitbringt.

Als erstes überschreiben wir die Methode onCreateDialog(Bundle bundle) folgendermaßen:

  @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        LayoutInflater inflater = getActivity().getLayoutInflater();
        this.view = inflater.inflate(R.layout.tagclouddialog, null);
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setView(this.view);
        builder.setMessage(getResources().getString(R.string.dateTimePickerDialogTitel))
                .setPositiveButton(getResources().getString(R.string.dateTimePickerDialogTitelOKBtn), new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                    }
                })
                .setNegativeButton(getResources().getString(R.string.dateTimePickerDialogTitelAbbrechenBtn), new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                    }
                });

        return builder.create();
    }

In der Zeile 3 und 4 wird das Layout aus der XML Datei geladen (dazu kommen wir später). Es wird sich das View Objekt für später als Instanzvariable gespeichert da wir von außen auf dieses zugriff benötigen (mit der dazugehörigen Getter Methode).

Die Zeilen 9 und 13 beinhalten die Events für die beiden Schaltflächen „OK“ und „Abbrechen“. Für die Verarbeitung der beiden Events benötigen wir folgendes Interface, welches wir uns erstellen:

import android.app.DialogFragment;

public interface DialogListener {
    public void onDialogPositiveClick(DialogFragment dialog);

    public void onDialogNegativeClick(DialogFragment dialog);
}

Dieses Interface stellt unsere beiden Methoden bereit, welches wir unserem Konstruktor in der Klasse TagCloudDialog übergeben.

public class TagCloudDialog extends DialogFragment{

    private View view;
    private DialogListener dialogListener;
    
    public TagCloudDialog(DialogListener dialogListener){
       this.dialogListener = dialogListener; 
    }

Das Layout „tagclouddialog.xml“

Die Datei „tagclouddialog.xml“ beinhaltet unsere UI Komponenten für den Dialog. In meinem Fall wird es eine Liste sein, in welcher man diverse Zeilen anwählen kann.

Somit wird das Layout wie folgt aussehen :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal">

    <ListView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tagsView" />
</LinearLayout>

Nun benötigen wir noch den Aufbau unseres anwählbaren ListItems welches ich unter dem Dateinamen „tagclouddialoglistitem.xml“ im Ordner „layout“ speichere.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent">


<CheckBox
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/tagCloudItemChkBox" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceMedium"
    android:text="Beispieltext"
    android:id="@+id/tagCloudItemTextView" />
</LinearLayout>

Befüllen der Liste mit Hilfe des ArrayAdapters

Für das befüllen der ListView benötigen wir eine Klasse welche die Klasse ArrayAdapter erweitert. Diese lege ich mir in mein Package „tagcloud“ ab. Es gibt diverse Tutorials wo dieses als innere Klasse umgesetzt wird jedoch finde ich dieses nicht für sinnvoll da so die Klasse unnötig lang wird.

Die Klasse „TagCloudListAdapter“

Wenn wir die Klasse ArrayAdapter mit extends hinzufügen müssen wir mindestens einen Kontruktor überladen.

import android.content.Context;
import android.widget.ArrayAdapter;


public class TagCloudListAdapter extends ArrayAdapter<TagItem> {

 public TagCloudListAdapter(Context context, int resource, List<TagItem> tagItems) {
   super(context, resource,tagItems);
  }
}

Zuweisen der View für die Darstellung der CheckboxItems

Um der ListView unser benutzerdefiniertes Aussehen zu verpassen (tagclouddialog.xml) müssen wir folgende Methode implementieren.

@Override
public View getView(int position, View convertView, ViewGroup parent) {}

In dieser Methode erstellen wir die View für die ListItems.

 @Override
    public View getView(int position, View view, ViewGroup parent) {
        LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = vi.inflate(R.layout.tagclouddialoglistitem, null);

        TagItem tagItem = this.tagIitems.get(position);
        CheckBox chkBox = (CheckBox) view.findViewById(R.id.tagCloudItemChkBox);
        chkBox.setChecked(tagItem.isSelected());
        TextView textView = (TextView) view.findViewById(R.id.tagCloudItemTextView);
        textView.setText(tagItem.getText());

        return view;
    }

Nun müssen wir an der Checkbox ein Eventhandler registrieren damit wir die gewählten Tags später auslesen können.

Es ist darauf zu achten das in der Zeile 1 die Variable „tagItem“ final ist damit diese auf dem View.OnClickListener erreichbar ist. (Sollte dieses nicht sein gibt der Compiler eine aussagekräftige Fehlermeldung, bzw. die IDE wird vorher dieses durch eine Meldung anzeigen.)

final TagItem tagItem = this.tagIitems.get(position);
CheckBox chkBox = (CheckBox) view.findViewById(R.id.tagCloudItemChkBox);
chkBox.setSelected(tagItem.isSelected());
chkBox.setOnClickListener(new View.OnClickListener() {
       public void onClick(View v) {
            CheckBox cb = (CheckBox) v;
            tagItem.setSelected(cb.isChecked());
       }
});

Registrieren des Adapters an der ListView

Nachdem wir die Logik für die ListView implementiert haben, wird nun der Adapter an der ListView angemeldet / registriert.

ListView listView = (ListView) this.view.findViewById(R.id.tagsView);
listView.setAdapter(new TagCloudListAdapter(getActivity().getApplicationContext(), R.layout.tagclouddialoglistitem, tagItems));

Da ich den Adapter in einer eigenen Klasse geschrieben habe (quasi keine innere Klasse der Klasse TagCloudDialog) muss ich den Context übergeben.

Interaktion zwischen dem Dialog und der Activity

Nun noch die Schaltflächen für die Interaktion mit der übergeordneten Activity bestücken.
In der Zeile 6 & 11 werden die Methoden aus dem Interface „DialogListener“ aufgerufen.

 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
 builder.setView(this.view);
 builder.setMessage(getResources().getString(R.string.tagCloudDialogTitel))
                .setPositiveButton(getResources().getString(R.string.okBtn), new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        dialogListener.onDialogPositiveClick(tagCloudDialog);
                    }
                })
                .setNegativeButton(getResources().getString(R.string.abbrechenBtn), new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        dialogListener.onDialogNegativeClick(tagCloudDialog);
                    }
                });

Event für die Schaltfläche „OK“

Diese Methode

  • entfernt als erstes alle TagItemViews aus dem LinearLayout,
  • durchläuft die TagItems mit einer For Each Schleife und,
  • wenn das TagItem selektiert ist wird dieses dem LinearLayout hinzugefügt.
@Override
public void onDialogPositiveClick(DialogFragment dialog) {
    LinearLayout tagCloud = (LinearLayout) this.view.findViewById(R.id.tagCloudLinearLayout);
    tagCloud.removeAllViews();
    for (TagItem tagItem : this.tagItems) {
        if (tagItem.isSelected()) {
            TagItemView item = new TagItemView(this.view.getContext(), this, tagItem);
            this.tagViewItems.add(item);
            tagCloud.addView(item, getLayoutParams(0));
        }
    }
}

Event für die Schaltfläche „Abbrechen“

Das Event für die Schaltfläche „Abbrechen“ muss nicht extra programmiert werden, denn dieses hat sein Verhalten von dem AlertDialog geerbt.

Schreibe einen Kommentar Antworten abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Fragen oder Feedback?

Du hast eine Idee, brauchst Hilfe oder möchtest Feedback loswerden?
Support-Ticket erstellen

Newsletter abonnieren

Bleib auf dem Laufenden: Erhalte regelmäßig Updates zu neuen Projekten, Tutorials und Tipps rund um Arduino, ESP32 und mehr – direkt in dein Postfach.

Jetzt Newsletter abonnieren

Unterstütze meinen Blog

Wenn dir meine Inhalte gefallen, freue ich mich über deine Unterstützung auf Tipeee.
So hilfst du mit, den Blog am Leben zu halten und neue Beiträge zu ermöglichen.

draeger-it.blog auf Tipeee unterstützen

Vielen Dank für deinen Support!
– Stefan Draeger

Kategorien

Tools

  • Unix-Zeitstempel-Rechner
  • ASCII Tabelle
  • Spannung, Strom, Widerstand und Leistung berechnen
  • Widerstandsrechner
  • 8×8 LED Matrix Tool
  • 8×16 LED Matrix Modul von Keyestudio
  • 16×16 LED Matrix – Generator

Links

Blogverzeichnis Bloggerei.de TopBlogs.de das Original - Blogverzeichnis | Blog Top Liste Blogverzeichnis trusted-blogs.com

Stefan Draeger
Königsberger Str. 13
38364 Schöningen

Tel.: 01778501273
E-Mail: info@draeger-it.blog

Folge mir auf

  • Impressum
  • Datenschutzerklärung
  • Disclaimer
  • Cookie-Richtlinie (EU)
©2025 Technik Blog | Built using WordPress and Responsive Blogily theme by Superb
Cookie-Zustimmung verwalten
Wir verwenden Technologien wie Cookies, um Geräteinformationen zu speichern und/oder darauf zuzugreifen. Wir tun dies, um das Surferlebnis zu verbessern und um personalisierte Werbung anzuzeigen. Wenn Sie diesen Technologien zustimmen, können wir Daten wie das Surfverhalten oder eindeutige IDs auf dieser Website verarbeiten. Wenn Sie Ihre Zustimmung nicht erteilen oder zurückziehen, können bestimmte Funktionen beeinträchtigt werden.
Funktional Immer aktiv
Die technische Speicherung oder der Zugang ist unbedingt erforderlich für den rechtmäßigen Zweck, die Nutzung eines bestimmten Dienstes zu ermöglichen, der vom Teilnehmer oder Nutzer ausdrücklich gewünscht wird, oder für den alleinigen Zweck, die Übertragung einer Nachricht über ein elektronisches Kommunikationsnetz durchzuführen.
Vorlieben
Die technische Speicherung oder der Zugriff ist für den rechtmäßigen Zweck der Speicherung von Präferenzen erforderlich, die nicht vom Abonnenten oder Benutzer angefordert wurden.
Statistiken
Die technische Speicherung oder der Zugriff, der ausschließlich zu statistischen Zwecken erfolgt. Die technische Speicherung oder der Zugriff, der ausschließlich zu anonymen statistischen Zwecken verwendet wird. Ohne eine Vorladung, die freiwillige Zustimmung deines Internetdienstanbieters oder zusätzliche Aufzeichnungen von Dritten können die zu diesem Zweck gespeicherten oder abgerufenen Informationen allein in der Regel nicht dazu verwendet werden, dich zu identifizieren.
Marketing
Die technische Speicherung oder der Zugriff ist erforderlich, um Nutzerprofile zu erstellen, um Werbung zu versenden oder um den Nutzer auf einer Website oder über mehrere Websites hinweg zu ähnlichen Marketingzwecken zu verfolgen.
Optionen verwalten Dienste verwalten Verwalten von {vendor_count}-Lieferanten Lese mehr über diese Zwecke
Einstellungen anzeigen
{title} {title} {title}