Parçadaki iletişim kutusu gösterilsin mi?


119

Düzenli bir diyalog göstermesi gereken bazı parçalarım var. Bu iletişim kutularında kullanıcı bir evet / hayır cevabı seçebilir ve ardından parça buna göre davranmalıdır.

Şimdi, Fragmentsınıfın onCreateDialog()geçersiz kılmak için bir yöntemi yok, bu yüzden diyalogları dışında, kapsama alanına uygulamalıyım sanırım Activity. Sorun değil, ama sonra Activityseçilen cevabı bir şekilde bölüme geri bildirmek gerekiyor. Elbette burada bir geri arama modeli kullanabilirim, böylece parça kendisini Activitybir dinleyici sınıfına kaydeder ve Aktivite bunun aracılığıyla yanıtı geri bildirir veya bunun gibi bir şey.

Ancak bu, bir parça içinde "basit" bir evet-hayır diyalogu göstermek gibi basit bir görev için oldukça büyük bir karmaşa gibi görünüyor. Ayrıca, bu şekilde benim Fragmentdaha az bağımsız olurum.

Bunu yapmanın daha temiz bir yolu var mı?

Düzenle:

Bu sorunun cevabı, Fragments'taki diyalogları görüntülemek için DialogFragments'ın nasıl kullanılması gerektiğini gerçekten ayrıntılı olarak açıklamıyor. Yani AFAIK, gitmenin yolu:

  1. Bir Parça Göster.
  2. Gerektiğinde, bir DialogFragment örneğini oluşturun.
  3. İle, orijinal Parçayı bu DialogFragment'ın hedefi olarak ayarlayın .setTargetFragment().
  4. Orijinal Parçadan .show () ile DialogFragment'ı gösterin.
  5. Kullanıcı bu DialogFragment üzerinde bir seçenek seçtiğinde, orijinal Fragmanı bu seçim hakkında bilgilendirin (örneğin, kullanıcı 'evet'i tıkladı), orijinal Parçanın referansını .getTarget () ile alabilirsiniz.
  6. DialogFragment'ı kapatın.

1
Tekniğiniz, ekran dönüşünün gerçekleştiği durumlar dışında çalışır. O zaman yaklaşıyorum. Herhangi bir fikir?
Weston

@Weston, Zsombor'un ilk cevabına bir göz atın: stackoverflow.com/questions/8235080/…
mightimaus

Yanıtlar:


37

Bunun yerine bir DialogFragment kullanmalısınız.


9
Ne yazık ki bu yaklaşım, önceki Android revizyonlarının klasik yönetilen diyalog yaklaşımından biraz daha ayrıntılıdır, ancak artık tercih edilen yöntemdir. Ve yöntemlerini Activitykullanarak tamamen referans vermekten kaçınabilirsiniz , böylece doğrudan çağrı parçasına geri bildirimde bulunabilirsiniz (yönlendirme değişikliklerinden sonra bile). putFragmentgetFragmentFragmentManagerDialogFragment
Dave

Ya Diyalogları görüntülemesi gereken bir ListFragment'ınız varsa, ikisini birden genişletemezsiniz
marchinram

16
ListFragment alt sınıfı, DialogFragment'ı alt sınıflandırarak değil, yenilerini başlatarak DialogFragments'ı kullanır. (Bir DialogFragment, Dialog'ları görüntüleyebilen bir Fragment değil, Fragment olarak uygulanan bir iletişim kutusudur.)
nmr

4
Lütfen biraz pasaj ekleyin, böylece daha kolay anlayabiliriz
Arpit Patel

35

Bir DialogFragment kullanmanın en iyi seçenek olduğuna dair önceden kabul edilmiş cevaba ihtiyatla şüphe etmeliyim. DialogFragment amaçlanan (birincil) amacı fragmanlarını görüntülemek için gibi görünüyor vardır değil ekran parçalarına kendilerini diyaloglar, sahip ekrana diyaloglar.

Diyalog ve parça arasında arabuluculuk yapmak için parçanın etkinliğini kullanmanın tercih edilen seçenek olduğuna inanıyorum.


10
Yönetilen diyaloglar ( onCreateDialog) yaklaşımı yakında kullanımdan kaldırılacağından, buna katılmıyorum ve bunun DialogFragmentgerçekten de doğru olduğunu söyleyebilirim .
Dave

4
Kabul edilen yanıt, ListFragment, AFAICS yerine Dialog yerine DialogFragment kullanılması anlamına gelir.
nmr

Aslında bir iletişim kutusu parçası hem bir iletişim kutusu hem de normal bir parça olarak kullanılabilir - gömme developer.android.com/reference/android/app/DialogFragment.html
Clive Jefferies

@CliveJefferies Yapabilir, ancak yine de kendi içinden diğer diyalogları göstermesi beklenmiyor. Sanırım buradaki adamlar soruyu yanlış anlıyor.
Marcel Bro

@anoniim bu, diyalog parçasının nasıl kullanıldığına bağlıdır. Normal bir parça olarak kullanılıyorsa sorun değil. Bir diyalog olarak kullanılıyorsa, evet, başka bir diyalog göstermemelisiniz.
Clive Jefferies

24

İşte evet / hayır DialogFragment'ın tam bir örneği:

Sınıf:

public class SomeDialog extends DialogFragment {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new AlertDialog.Builder(getActivity())
            .setTitle("Title")
            .setMessage("Sure you wanna do this!")
            .setNegativeButton(android.R.string.no, new OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    // do nothing (will close dialog)
                }
            })
            .setPositiveButton(android.R.string.yes,  new OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    // do something
                }
            })
            .create();
    }
}

Diyaloğu başlatmak için:

        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        // Create and show the dialog.
        SomeDialog newFragment = new SomeDialog ();
        newFragment.show(ft, "dialog");

Ayrıca sınıfın onClickListener uygulamasını uygulamasına ve gömülü dinleyiciler yerine bunu kullanmasına izin verebilirsiniz.

Aktiviteye Geri Dönüş

Geri aramayı uygulamak istiyorsanız, bu işlem şu şekilde yapılır:

YourActivity extends Activity implements OnFragmentClickListener

ve

@Override
public void onFragmentClick(int action, Object object) {
    switch(action) {
        case SOME_ACTION:
        //Do your action here
        break;
    }
}

Geri arama sınıfı:

public interface OnFragmentClickListener {
    public void onFragmentClick(int action, Object object);
}

Ardından bir parçadan geri arama gerçekleştirmek için dinleyicinin şu şekilde eklendiğinden emin olmalısınız:

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    try {
        mListener = (OnFragmentClickListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement listeners!");
    }
}

Ve şöyle bir geri arama yapılır:

mListener.onFragmentClick(SOME_ACTION, null); // null or some important object as second parameter.

4
Bu, bir
Parçadan

@raveN, daha sonra parçayı başlatacak olan aktivitenize bir geri arama yaparsınız.
Warpzit

@Warpzit Kapsamlı cevap için teşekkürler. FragmentManager'a dokunmaktan korkuyorum, ki bu zaten aptalca şeyler yapıyor ... onClick olaylarını kullanıcı girdisine ihtiyaç duyan (Diyalog dışı) Parçaya nasıl geri aktarabilirim? BTW, işlem backstack'e eklenmemeli mi?
kaay

@kaay etkinlikten, verilen parçada yeni girdiye ihtiyaç duyan herhangi bir genel yöntemi çağırabilirsiniz. Oradan yeni içerikle güncellenmesi oldukça kolay olacaktır.
Warpzit

1
@RichardLeMesurier Aslında, parçalar iniş ve çıkışlardır.
Warpzit

13

Benim için şuydu:

MyFragment:

public class MyFragment extends Fragment implements MyDialog.Callback
{
    ShowDialog activity_showDialog;

    @Override
    public void onAttach(Activity activity)
    {
        super.onAttach(activity);
        try
        {
            activity_showDialog = (ShowDialog)activity;
        }
        catch(ClassCastException e)
        {
            Log.e(this.getClass().getSimpleName(), "ShowDialog interface needs to be     implemented by Activity.", e);
            throw e;
        }
    }

    @Override
    public void onClick(View view) 
    {
        ...
        MyDialog dialog = new MyDialog();
        dialog.setTargetFragment(this, 1); //request code
        activity_showDialog.showDialog(dialog);
        ...
    }

    @Override
    public void accept()
    {
        //accept
    }

    @Override
    public void decline()
    {
        //decline
    }

    @Override
    public void cancel()
    {
        //cancel
    }

}

myDialog:

public class MyDialog extends DialogFragment implements View.OnClickListener
{
    private EditText mEditText;
    private Button acceptButton;
    private Button rejectButton;
    private Button cancelButton;

    public static interface Callback
    {
        public void accept();
        public void decline();
        public void cancel();
    }

    public MyDialog()
    {
        // Empty constructor required for DialogFragment
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View view = inflater.inflate(R.layout.dialogfragment, container);
        acceptButton = (Button) view.findViewById(R.id.dialogfragment_acceptbtn);
        rejectButton = (Button) view.findViewById(R.id.dialogfragment_rejectbtn);
        cancelButton = (Button) view.findViewById(R.id.dialogfragment_cancelbtn);
        acceptButton.setOnClickListener(this);
        rejectButton.setOnClickListener(this);
        cancelButton.setOnClickListener(this);
        getDialog().setTitle(R.string.dialog_title);
        return view;
    }

    @Override
    public void onClick(View v)
    {
        Callback callback = null;
        try
        {
            callback = (Callback) getTargetFragment();
        }
        catch (ClassCastException e)
        {
            Log.e(this.getClass().getSimpleName(), "Callback of this class must be implemented by target fragment!", e);
            throw e;
        }

        if (callback != null)
        {
            if (v == acceptButton)
            {   
                callback.accept();
                this.dismiss();
            }
            else if (v == rejectButton)
            {
                callback.decline();
                this.dismiss();
            }
            else if (v == cancelButton)
            {
                callback.cancel();
                this.dismiss();
            }
        }
    }
}

Aktivite:

public class MyActivity extends ActionBarActivity implements ShowDialog
{
    ..

    @Override
    public void showDialog(DialogFragment dialogFragment)
    {
        FragmentManager fragmentManager = getSupportFragmentManager();
        dialogFragment.show(fragmentManager, "dialog");
    }
}

DialogFragment düzeni:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/dialogfragment_textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="10dp"
        android:text="@string/example"/>

    <Button
        android:id="@+id/dialogfragment_acceptbtn"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:layout_centerHorizontal="true"
        android:layout_below="@+id/dialogfragment_textview"
        android:text="@string/accept"
        />

    <Button
        android:id="@+id/dialogfragment_rejectbtn"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_alignLeft="@+id/dialogfragment_acceptbtn"
        android:layout_below="@+id/dialogfragment_acceptbtn"
        android:text="@string/decline" />

     <Button
        android:id="@+id/dialogfragment_cancelbtn"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="20dp"
        android:layout_alignLeft="@+id/dialogfragment_rejectbtn"
        android:layout_below="@+id/dialogfragment_rejectbtn"
        android:text="@string/cancel" />

     <Button
        android:id="@+id/dialogfragment_heightfixhiddenbtn"
        android:layout_width="200dp"
        android:layout_height="20dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="20dp"
        android:layout_alignLeft="@+id/dialogfragment_cancelbtn"
        android:layout_below="@+id/dialogfragment_cancelbtn"
        android:background="@android:color/transparent"
        android:enabled="false"
        android:text=" " />
</RelativeLayout>

Adından da anlaşılacağı gibi, dialogfragment_heightfixhiddenbtnalt düğmenin yüksekliğinin yarıya indirildiğini söylememe rağmen düzeltmenin bir yolunu bulamadım wrap_content, bu yüzden bunun yerine ikiye "kesilecek" gizli bir düğme ekledim. Hack için üzgünüm.


1
+ 1 ile referans kümesi, setTargetFragment()döndürmeden sonra Etkinlik / Parça kümesini yeniden başlattığında sistem tarafından doğru şekilde yeniden oluşturulur. Böylece referans otomatik olarak yeni hedefi gösterecektir.
Richard Le Mesurier

Yine de ButterKnife'ı gün içinde kullanmadığım için burnuma yumruk atardım. ButterKnife kullanın, görüşünüzü daha güzel hale getirir.
EpicPandaForce

Ve olayı Fragment'tan Activity'e göndermek için Otto'yu kullanabilirsiniz, böylece arayüz ekleme sihrine ihtiyacınız olmaz. Otto örneği burada: stackoverflow.com/a/28480952/2413303
EpicPandaForce

@EpicPandaForce Lütfen "ShowDialog" Arayüzünü / Sınıfını ekleyebilir misiniz? Örneğinizde eksik olan tek şey bu.
ntrch

@ntrch oldupublic interface ShowDialog { void showDialog(DialogFragment dialogFragment); }
EpicPandaForce

3
 public void showAlert(){


     AlertDialog.Builder alertDialog = new AlertDialog.Builder(getActivity());
     LayoutInflater inflater = getActivity().getLayoutInflater();
     View alertDialogView = inflater.inflate(R.layout.test_dialog, null);
     alertDialog.setView(alertDialogView);

     TextView textDialog = (TextView) alertDialogView.findViewById(R.id.text_testDialogMsg);
     textDialog.setText(questionMissing);

     alertDialog.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
         public void onClick(DialogInterface dialog, int which) {
             dialog.cancel();
         }
     });
     alertDialog.show();

}

.test_dialog xml özelinde


2

Ben de yeni başlayan biriyim ve dürüst olmak gerekirse anlayabileceğim veya uygulayabileceğim tatmin edici bir cevap bulamadım.

İşte istediğimi elde etmeme gerçekten yardımcı olduğum bir dış bağlantı. Çok basit ve takip etmesi de kolay.

http://www.helloandroid.com/tutorials/how-display-custom-dialog-your-android-application

KODLA BAŞARMAYA ÇALIŞTIĞIM ŞEY:

Fragment barındıran bir MainActivity var. Kullanıcı girişi istemek ve ardından girişi buna göre işlemek için düzenin üstünde bir iletişim kutusu görünmesini istedim. Ekran görüntüsüne bakın

İşte parçamın onCreateView görünümü

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

    View rootView = inflater.inflate(R.layout.fragment_home_activity, container, false);

    Button addTransactionBtn = rootView.findViewById(R.id.addTransactionBtn);

    addTransactionBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Dialog dialog = new Dialog(getActivity());
            dialog.setContentView(R.layout.dialog_trans);
            dialog.setTitle("Add an Expense");
            dialog.setCancelable(true);

            dialog.show();

        }
    });

Umarım bu sana yardımcı olur

Herhangi bir karışıklık olursa bana haber ver. :)


0
    public static void OpenDialog (Activity activity, DialogFragment fragment){

    final FragmentManager fm = ((FragmentActivity)activity).getSupportFragmentManager();

    fragment.show(fm, "tag");
}

3
lütfen cevabınıza biraz açıklama ekleyin
RealCheeseLord
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.