조각에서 대화를 표시 하시겠습니까?


119

일반 대화 상자를 표시해야하는 조각이 있습니다. 이 대화 상자에서 사용자는 예 / 아니요 응답을 선택할 수 있으며 그에 따라 조각이 작동해야합니다.

이제 Fragment클래스에는 onCreateDialog()재정의 할 메서드 가 없으므로 포함 된 .NET Framework에서 대화 상자를 외부에 구현해야한다고 생각합니다 Activity. 괜찮지 만 Activity선택한 답변을 어떻게 든 조각에보고해야합니다. 물론 여기에서 콜백 패턴을 사용할 수 있으므로 조각 Activity은 리스너 클래스에 자신을 등록 하고 활동은이를 통해 응답을 다시보고합니다.

그러나 이것은 단편에 "간단한"예-아니오 대화 상자를 표시하는 것과 같은 간단한 작업에는 상당히 엉망인 것 같습니다. 또한, 이렇게하면 내 Fragment자급 자족이 줄어들 것입니다.

이를 수행하는 더 깨끗한 방법이 있습니까?

편집하다:

이 질문에 대한 대답은 DialogFragments를 사용하여 Fragments에서 대화 상자를 표시하는 방법을 자세히 설명하지 않습니다. 그래서 AFAIK,가는 길은 :

  1. 조각을 표시합니다.
  2. 필요한 경우 DialogFragment를 인스턴스화합니다.
  3. 을 사용하여 원본 조각을이 DialogFragment의 대상으로 설정합니다 .setTargetFragment().
  4. 원본 Fragment에서 .show ()를 사용하여 DialogFragment를 표시합니다.
  5. 사용자가이 DialogFragment에서 일부 옵션을 선택하면이 선택에 대해 원래 Fragment에 알리면 (예 : 사용자가 'yes'를 클릭) .getTarget ()을 사용하여 원래 Fragment의 참조를 가져올 수 있습니다.
  6. DialogFragment를 닫습니다.

1
화면 회전이 발생하는 경우를 제외하고는 기술이 작동합니다. 나는 그때 가까이에 힘을 얻습니다. 어떤 아이디어?
Weston

@Weston은 Zsombor의 첫 번째 답변을 확인합니다. stackoverflow.com/questions/8235080/…
mightimaus

답변:


37

대신 DialogFragment 를 사용해야합니다 .


9
안타깝게도이 접근 방식은 이전 Android 버전의 기존 관리 대화 상자 접근 방식보다 조금 더 장황하지만 이제는 선호되는 방법입니다. ActivityputFragmentgetFragment메서드를 사용하여을 (를) 사용하여 전체를 참조하는 것을 피할 수 있습니다. 그러면 에서 호출 프래그먼트에 직접보고 FragmentManager할 수 DialogFragment있습니다 (방향 변경 후에도).
Dave

당신이 필요 대화 상자를 표시하는 ListFragment이있는 경우, 그들에게 모두 확장 할 수 없습니다 무엇
marchinram

16
ListFragment 서브 클래스는 DialogFragment를 서브 클래 싱하는 것이 아니라 새로운 것을 인스턴스화하여 DialogFragments를 사용합니다. (DialogFragment는 Dialogs를 표시 할 수있는 Fragment가 아니라 Fragment로 구현 된 대화 상자입니다.)
nmr

4
우리가 eaisly 이해할 수 있도록 몇 조각을 추가하세요
Arpit 파텔

35

DialogFragment를 사용하는 것이 최선의 선택이라는 이전에 받아 들여진 대답을 조심스럽게 의심해야합니다. DialogFragment의 목적으로 (주)의 목적은 조각을 표시하는 것 입니다 하지 디스플레이 조각에 자신을 대화 상자, 디스플레이 대화 상자를.

프래그먼트의 활동을 사용하여 대화와 프래그먼트 사이를 중재하는 것이 바람직한 옵션이라고 생각합니다.


10
관리되는 대화 상자 ( onCreateDialog) 접근 방식이 곧 더 이상 사용되지 않을 예정이므로 동의하지 않으며 이것이 DialogFragment실제로 갈 길이 라고 말합니다 .
Dave

4
수락 된 대답은 AFAICS 인 ListFragment 대신 DialogFragment 대신 DialogFragment를 사용하는 것을 의미합니다.
nmr 2011 년

실제로 대화 조각은 대화 상자와 일반 조각 모두로 사용할 수 있습니다. 임베딩 developer.android.com/reference/android/app/DialogFragment.html
Clive Jefferies

@CliveJefferies 할 수는 있지만 여전히 자체 내에서 다른 대화 상자를 표시해서는 안됩니다. 여기 사람들이 잘못된 질문을 받고 있다고 생각합니다.
Marcel Bro 2016 년

@anoniim 대화 조각이 사용되는 방식에 따라 다릅니다. 일반 조각으로 사용하면 괜찮습니다. 대화 상자로 사용중인 경우 예, 다른 대화 상자를 표시하지 않아야합니다.
Clive Jefferies 2016 년

24

예 / 아니오 DialogFragment의 전체 예는 다음과 같습니다.

클래스:

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();
    }
}

대화를 시작하려면 :

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

클래스가 onClickListener를 구현하고 포함 된 리스너 대신 사용하도록 할 수도 있습니다.

활동에 대한 콜백

콜백을 구현하려면 활동에서 수행되는 방법입니다.

YourActivity extends Activity implements OnFragmentClickListener

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

콜백 클래스 :

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

그런 다음 조각에서 콜백을 수행하려면 리스너가 다음과 같이 연결되어 있는지 확인해야합니다.

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

그리고 콜백은 다음과 같이 수행됩니다.

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

4
이것은 Fragment에서 시작하는 방법을 설명하지 않습니다
akohout

@raveN 당신은 단순히 당신의 활동에 콜백을 만들고 조각을 시작할 것입니다.
Warpzit 2014 년

@Warpzit 포괄적 인 답변에 감사드립니다. 나는 이미 경건하지 않은 일을하고있는 FragmentManager를 만지는 것이 두렵습니다. 어떻게 onClick 이벤트를 사용자 입력이 필요한 (대화가 아닌) Fragment로 다시 전달할 수 있습니까? BTW, 트랜잭션을 백 스택에 추가하면 안 되나요?
kaay

활동에서 @kaay 새 입력이 필요한 주어진 조각에서 모든 공용 메서드를 호출 할 수 있습니다. 거기에서 새로운 콘텐츠로 매우 쉽게 업데이트 할 수 있습니다.
Warpzit 2014

1
@RichardLeMesurier 실제로 조각은 기복입니다.
Warpzit 2014 년

13

저에게는 다음과 같습니다.

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();
            }
        }
    }
}

활동:

public class MyActivity extends ActionBarActivity implements ShowDialog
{
    ..

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

DialogFragment 레이아웃 :

<?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>

이름에서 알 수 있듯이 dialogfragment_heightfixhiddenbtn라고 말했지만 하단 버튼의 높이가 반으로 잘리는 것을 고칠 방법을 찾을 수 wrap_content없었기 때문에 대신에 숨겨진 버튼을 추가하여 반으로 "잘립니다". 해킹 죄송합니다.


1
+1 참조 세트 setTargetFragment()는 회전 후 활동 / 조각 세트를 다시 시작할 때 시스템에 의해 올바르게 다시 생성됩니다. 따라서 참조는 자동으로 새 대상을 가리 킵니다.
Richard Le Mesurier 2014 년

하지만 예전에는 ButterKnife를 사용하지 않았기 때문에 코를 찔렀습니다. ButterKnife를 사용하면 뷰 처리가 훨씬 더 예뻐집니다.
EpicPandaForce 2014

그리고 Otto를 사용하여 Fragment에서 Activity로 이벤트를 보낼 수 있으므로 인터페이스 연결 마법이 필요하지 않습니다. Otto 예 : stackoverflow.com/a/28480952/2413303
EpicPandaForce

@EpicPandaForce "ShowDialog"인터페이스 / 클래스를 추가 할 수 있습니까? 귀하의 예에서 누락 된 유일한 것입니다.
ntrch

@ntrch it waspublic interface ShowDialog { void showDialog(DialogFragment dialogFragment); }
EpicPandaForce jul.

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 사용자 정의입니다.


2

나는 초보자이고 솔직히 이해하거나 구현할 수있는 만족스러운 대답을 찾지 못했습니다.

여기 제가 원하는 것을 달성하는 데 도움이 된 외부 링크가 있습니다. 매우 간단하고 따라하기 쉽습니다.

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

코드로 달성하기 위해 시도한 것은 다음과 같습니다.

Fragment를 호스팅하는 MainActivity가 있습니다. 사용자 입력을 요청한 다음 그에 따라 입력을 처리하는 대화 상자가 레이아웃 상단에 나타나기를 원했습니다. 스크린 샷보기

내 조각의 onCreateView는 다음과 같습니다.

@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();

        }
    });

도움이 되길 바랍니다

혼동이 있으면 알려주세요. :)


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

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

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

3
당신의 대답에 약간의 explaination를 추가하십시오
RealCheeseLord
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.