Android Dialog verstecken, statt zu schliessen

RezaScript

Bekanntes Mitglied
Hallo,

ich benutze DialogFragment und habe ein Problem beim Schliessen des Dialogs.

Wenn der Dialog geschlossen wird, gehen in der View alle Änderungen verloren. Beim nächsten Aufruf des Dialogs sieht die View aus wie am Anfang und das möchte ich vermeiden. Beim Schliessen sollen also alle Änderungen bleiben, so wie sie waren.

Ich habe zwar schon eine Lösung dafür aber mir gefällt diese Lösung nicht. Die Lösung wäre, via Interface alle Änderungen an Activity geben und beim erneuten Aufruf überprüfen, welche Änderungen existieren und diese dann entsprechend setzen. Das würde zwar funktionieren, ist bei meinem View aber viel zu aufwändig! Den die View des Dialogs enthält viele Details wie Audio, Video, Textfelder, Animationen und und und.

Ich denke, dass es hierbei eine einfachere Lösung geben muss. Ungefähr so stelle ich es mir vor:
Bei onDismiss() soll der Dialog nicht geschlossen werden, sondern lediglich "versteckt", wie z. B. dialog.setVisibility(View.GONE);

Damit der Dialog nicht geschlossen wird, benutze ich in onCreateView(): setCancelable(false);
Beim Überschreiben von onDismiss() würde ich gerne setVisibility(View.GONE); verwenden, finde dazu aber keine Referenz. Mit getDialog().setVisibility(View.GONE); scheint es jedenfalls nicht zu funktionieren.
 
Hallo vielleicht hilft das Objekt von Fragment nicht zu zerstören.
Bein zweiten Aufruf also kein neues Objekt von der Fragment Klasse zu erstellen.
Das gleiche Objekt für den zweiten Aufruf wider zu benutzen.

Ein klassischer Start geht ja in etwa so

Java:
MyDialogFragment dialogFragment = new MyDialogFragment();
FragmentTranscation ft = getSupportFragmentManager().beginTransaction();
Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
ft.addToBackStack(null);
dialogFragment.show(ft, "dialog");

Teste doch vor dem Start ob das „dialogfragment“ noch exitirt.
Dazu würde ich die Variable aus Instanzvariable in der Activity halten.

Dies könnte ein Versuch wert sein habe es nicht getestet.
 
Also generell ist es aus meiner Sicht immer eine gute Idee, Daten und UI zu trennen. Die UI zeigt dann die Daten des Models an. Aber ein I Element besitzt die Daten nicht.

So kann ein Fragment die Daten einer Instanz einer Modelklasse anzeigen, Änderungen können in der Instanz wiedergespiegelt werden u.s.w. Aber die Instanz selbst kann dann auch an anderer Stelle referenziert sein. Bei einer Android App könnte dies in der Activity sein.

Dann wäre es also kein Thema, wenn das Fragment geschlossen und wieder neu geöffnet wird (so beim Öffnen wieder die Daten der einen Instanz verwendet werden).

Also eigentlich ein 08/15 Pattern, das man immer wieder sieht und da dürfte es eigentlich keinen Grund geben, irgendwie zu tricksen um ein Fragment, das geschlossen wird, ggf doch nicht zu schließen oder so.
 
Hallo hier mal ein Beispiel mit ViewModel
Template Bottom Navigation Activity vom Studio.

Ich habe der Activity ein Model hinzugefügt in dem ich den String vom EditText im Fragment Dashboard speichere.
Mit dem Button wir es gespeichert.

Du kannst natürlich auch einen observer zum Speichen benutzen.


Java:
package com.example.myapplication;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class MainActivityViewModel extends ViewModel {
    private final MutableLiveData<String> mText1 ;

    public MainActivityViewModel() {

        mText1 = new MutableLiveData<>();
        mText1.setValue("");
    }

    public LiveData<String> getText1() {
        return mText1;
    }

    public void setEdittext(String text) {
        mText1.setValue(text);
    }

}

Java:
package com.example.myapplication.ui.dashboard;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;

import com.example.myapplication.MainActivityViewModel;
import com.example.myapplication.databinding.FragmentDashboardBinding;

public class DashboardFragment extends Fragment {

    private FragmentDashboardBinding binding;

    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        DashboardViewModel dashboardViewModel =
                new ViewModelProvider(this).get(DashboardViewModel.class);
        MainActivityViewModel activityViewModel= new ViewModelProvider(getActivity()).get(MainActivityViewModel.class);



        binding = FragmentDashboardBinding.inflate(inflater, container, false);
        View root = binding.getRoot();

        final TextView textView = binding.textDashboard;
        dashboardViewModel.getText().observe(getViewLifecycleOwner(), textView::setText);

        activityViewModel.getText1().observe(getViewLifecycleOwner(), binding.editText1::setText);


        binding.button.setOnClickListener(item -> {
            activityViewModel.setEdittext(binding.editText1.getText().toString());
        });

        return root;
    }



    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }
}

XML:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.dashboard.DashboardFragment">

    <TextView
        android:id="@+id/text_dashboard"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:textAlignment="center"
        android:textSize="20sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/editText1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="Name"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.497"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:text="Button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/editText1" />
</androidx.constraintlayout.widget.ConstraintLayout>
 
Damit der Dialog nicht geschlossen wird, benutze ich in onCreateView(): setCancelable(false);
Bedeutet für mich nicht das das Objekt nicht zerstört wird beim beenden zB beim Klick des Ok Button. Es verhindert nur das der Dialog nicht von außen zb der Activity abgebrochen werden kann. Ohne das einer der Dialog Button betätigt wird. Mert macht das nicht. Ist für das was du wisst nicht zu gebrauchen.



Eine andere Variante wäre den Dialog als Singelton zu halten.
Und natürlich selbst im Dialog auch zu beenden.

Was aber nur gehen wird bei einem Start mit FragmentManager.
Nicht neuer mit NavController.


Wobei ich das neuere ViewModel den vorrang geben würden.

Wollte es einfach nur mal erwähnt haben das es früher auch ging. Und das ViewModel von Android ist („ähnlich, fast ein Singelton ist“) wenn es an die Activity gekoppelt ist. Ist ja auch dazu gedacht um Daten zwischen den Fragmenten einfach zu tauschen.


[CODE lang="java" title="In der Activity"]FragmentManager fm = getFragmentManager();
DashboardFragment dashboardFragment = DashboardFragment.getInstance();
dashboardFragment.show(fm, "Dashboard");[/CODE]

Java:
public class DashboardFragment extends DialogFragment {

    private FragmentDashboardBinding binding;
    private static DashboardFragment single_instance = null;

    public static DashboardFragment getInstance() {
        if (single_instance == null)
            single_instance = new DashboardFragment();
        return single_instance;
    }

    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        binding = FragmentDashboardBinding.inflate(inflater, container, false);
        View root = binding.getRoot();

        binding.textDashboard.setText("This is dashboard fragment");

        binding.button.setOnClickListener(item -> {
            dismiss();
        });
        return root;
    }


    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }
}
 

Neue Themen


Zurück
Oben