[안드로이드] AlertDialog, Dialog란 무엇인가?

프로그래밍/Android 관련2017. 12. 14. 20:18

안녕하세요. 개발자 드리머즈입니다.


운영체제마다.. 비슷한 기능을 하는 클래스 들이 있습니다만 이름이 달라서 헷갈리는 경우가 있습니다.

그래서 이번 포스트에서.. 간단하게 안드로이드에서 AlertDialog와 Dialog가 무엇인지 정리하려고 합니다.


안드로이드 디벨로퍼 공식홈에 자료가 있습니다.

https://developer.android.com/guide/topics/ui/dialogs.html


Dialog를 한글로 "대화상자"라고 번역해놨네요.


대화상자는 사용자에게 결정을 내리거나 추가 정보를 입력하라는 프롬프트를 보내는 작은 창입니다. 대화상자는 화면을 가득 채우지 않으며 보통 사용자가 다음으로 계속 진행하기 전에 조치를 취해야 하는 모달 이벤트에 사용됩니다.


공식 홈에는 위와 같이 설명이 되어있습니다.




공식 홈에 나와있는 사진을 보면, 바로 이해가 될 것입니다.

화면의 일부만 가려서 응답은 받는 작은.. 대화상자?를 Dialog라고 합니다.


공식 홈에 따르면 주의할 점은,


Dialog 클래스가 대화상자의 기본 클래스이지만, Dialog를 직접 인스턴스화하는 것은 삼가야 합니다.


라고 합니다. 대신 서브 클래스(자식)인 AlertDialog나 DatePickerDialog, TimePickerDialog를 사용하라고 합니다.


제가 좀 더 자세히 설명을 적고 싶지만 공식홈의 내용이 상당히 좋기에..

공식홈을 직접 보실 것을 권장 드립니다.


링크 : https://developer.android.com/guide/topics/ui/dialogs.html


 

대화상자

대화상자는 사용자에게 결정을 내리거나 추가 정보를 입력하라는 프롬프트를 보내는 작은 창입니다. 대화상자는 화면을 가득 채우지 않으며 보통 사용자가 다음으로 계속 진행하기 전에 조치를 취해야 하는 모달 이벤트에 사용됩니다.

대화상자 디자인

언어 권장 사항을 비롯한 여러 가지 대화상자 디자인 방법에 관련된 정보는 대화상자 디자인 가이드를 읽어보세요.


Dialog 클래스가 대화상자의 기본 클래스이지만, Dialog를 직접 인스턴스화하는 것은 삼가야 합니다. 대신 다음 서브클래스 중 하나를 사용하세요.

AlertDialog
제목 하나, 최대 세 개의 버튼, 선택 가능한 품목 목록 또는 사용자 지정 레이아웃을 표시할 수 있는 대화상자입니다.
DatePickerDialog 또는 TimePickerDialog
미리 정의된 UI가 있는 대화상자로 사용자로 하여금 날짜 또는 시간을 선택할 수 있게 해줍니다.

이러한 클래스가 대화상자의 스타일과 구조를 정의하지만, 대화상자의 컨테이너로는 DialogFragment를 사용해야 합니다. DialogFragment 클래스는 대화상자를 만들고 그 외관을 관리하는 데 필요한 모든 컨트롤을 제공합니다. Dialog 객체에서 메서드를 호출하는 것 대신입니다.

대화상자를 관리하기 위해 DialogFragment를 사용하면 사용자가 Back 버튼을 누르거나 화면을 돌릴 때 등 수명 주기 이벤트를 올바르게 처리하도록 보장할 수 있습니다. DialogFragment 클래스를 사용하면 대화상자의 UI를 더 큰 UI에 포함시킬 수 있는 구성 요소로 재사용할 수도 있습니다. 이것은 기존의 Fragment와 똑같습니다(대화상자 UI를 크고 작은 화면에서 서로 다르게 나타나도록 하고자 하는 경우 등).

이 가이드의 다음 섹션에서는 DialogFragmentAlertDialog 객체와 함께 조합하여 사용하는 방법을 설명합니다. 날짜 또는 시간 선택기를 생성하고자 하는 경우, 대신 선택기 가이드를 읽으세요.

참고: DialogFragment 클래스는 원래 Android 3.0(API 레벨 11)에 추가되었기 때문에 이 문서에서는 지원 라이브러리와 함께 제공된 DialogFragment 클래스를 사용하는 법을 설명합니다. 이 라이브러리를 앱에 추가하면 Android 1.6 이상을 실행하는 기기에서 DialogFragment를 비롯하여 다른 API도 다양하게 사용할 수 있습니다. 앱의 최소 버전이 API 레벨 11 이상인 경우, DialogFragment의 프레임워크 버전을 사용해도 되지만, 이 문서에 있는 링크는 지원 라이브러리 API를 대상으로 한 것이라는 점을 유의하세요. 지원 라이브러리를 사용할 때에는 android.support.v4.app.DialogFragment 클래스를 가져와야 합니다. android.app.DialogFragment아닙니다.

대화상자 프래그먼트 생성


대단히 다양한 대화상자 디자인을 만들 수 있습니다. 사용자 지정 레이아웃은 물론 대화상자 디자인 가이드에서 설명한 것도 포함합니다. DialogFragment를 확장하고 onCreateDialog() 콜백 메서드에 AlertDialog를 생성하면 됩니다.

예를 들어 다음은 DialogFragment 내에서 관리되는 기본 AlertDialog입니다.

public class FireMissilesDialogFragment extends DialogFragment {
   
@Override
   
public Dialog onCreateDialog(Bundle savedInstanceState) {
       
// Use the Builder class for convenient dialog construction
       
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder
.setMessage(R.string.dialog_fire_missiles)
               
.setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
                   
public void onClick(DialogInterface dialog, int id) {
                       
// FIRE ZE MISSILES!
                   
}
               
})
               
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                   
public void onClick(DialogInterface dialog, int id) {
                       
// User cancelled the dialog
                   
}
               
});
       
// Create the AlertDialog object and return it
       
return builder.create();
   
}
}


그림 1. 하나의 메시지와 두 개의 작업 버튼이 있는 대화상자.

이제, 이 클래스의 인스턴스를 생성하고 해당 객체에서 show()를 호출하면 대화상자는 그림 1에 표시된 것처럼 나타납니다.

다음 섹션에서는 AlertDialog.Builder API를 사용하여 대화상자를 생성하는 것에 대해 좀 더 자세히 설명합니다.

대화상자가 얼마나 복잡한지에 따라 DialogFragment에서 여러 가지 다른 콜백 메서드를 구현할 수 있습니다. 그 중에는 기본적인 프래그먼트 수명 주기 메서드도 포함됩니다.

경고 대화상자 빌드


AlertDialog 클래스를 사용하면 여러 가지 대화상자 디자인을 구축할 수 있으며, 필요한 대화상자 클래스는 이것뿐인 경우도 많습니다. 그림 2에 표시된 것과 같이 경고 대화상자에는 세 가지 영역이 있습니다.


그림 2. 대화상자의 레이아웃.

  1. 제목

    이것은 선택 항목이며 콘텐츠 영역에 상세한 메시지, 목록 또는 사용자 지정 레이아웃이 채워져 있는 경우에만 사용해야 합니다. 단순한 메시지 또는 질문을 나타내야 하는 경우(그림 1의 대화상자), 제목은 없어도 됩니다.

  2. 콘텐츠 영역

    이것은 메시지, 목록 또는 다른 사용자 지정 레이아웃을 표시할 수 있습니다.

  3. 작업 버튼

    대화상자 하나에 작업 버튼이 세 개 이상 있으면 안 됩니다.

AlertDialog.Builder 클래스가 이와 같은 종류의 콘텐츠가 있는 AlertDialog를 생성할 수 있게 해주는 API를 제공하며, 여기에 사용자 지정 레이아웃도 포함됩니다.

AlertDialog를 구축하려면 다음과 같이 하면 됩니다.

// 1. Instantiate an AlertDialog.Builder with its constructor
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

// 2. Chain together various setter methods to set the dialog characteristics
builder
.setMessage(R.string.dialog_message)
       
.setTitle(R.string.dialog_title);

// 3. Get the AlertDialog from create()
AlertDialog dialog = builder.create();

다음 항목은 AlertDialog.Builder 클래스를 사용하여 다양한 대화상자 특성을 정의하는 방법을 보여줍니다.

버튼 추가

그림 2에 표시된 것과 같은 작업 버튼을 추가하려면 setPositiveButton()setNegativeButton() 메서드를 호출하면 됩니다.

AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Add the buttons
builder
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
           
public void onClick(DialogInterface dialog, int id) {
               
// User clicked OK button
           
}
       
});
builder
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
           
public void onClick(DialogInterface dialog, int id) {
               
// User cancelled the dialog
           
}
       
});
// Set other dialog properties
...

// Create the AlertDialog
AlertDialog dialog = builder.create();

set...Button() 메서드에는 버튼의 제목이 필요하고(문자열 리소스가 제공), 사용자가 버튼을 눌렀을 때 수행할 작업을 정의하는 DialogInterface.OnClickListener가 필요합니다.

추가할 수 있는 작업 버튼은 다음 세 가지입니다.

긍정적
이것은 수락하고 작업을 계속하는 데 사용해야 합니다("OK" 작업).
부정적
이것은 작업을 취소하는 데 사용해야 합니다.
중립적
이것은 사용자가 작업을 계속하고 싶지 않을 수 있지만 취소하고자 한다고 볼 수 없을 때 사용해야 합니다. 이것은 긍정적 버튼과 부정적 버튼 사이에 나타납니다. 이런 작업을 예로 들면 "Remind me later" 등이 있습니다.

AlertDialog에는 각 버튼 유형을 하나씩만 추가할 수 있습니다. 다시 말해, "긍정적" 버튼이 한 개 이상 있으면 안 됩니다.




그림 3. 제목과 목록이 있는 대화상자.

목록 추가

AlertDialog API와 함께 사용 가능한 목록은 세 가지 종류가 있습니다.

  • 일반적인 단일 선택 목록
  • 지속적인 단일 선택 목록(라디오 버튼)
  • 지속적인 다중 선택 목록(체크박스)

그림 3에 표시된 것과 같은 단일 선택 목록을 생성하려면 setItems() 메서드를 사용하면 됩니다.

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
   
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    builder
.setTitle(R.string.pick_color)
           
.setItems(R.array.colors_array, new DialogInterface.OnClickListener() {
               
public void onClick(DialogInterface dialog, int which) {
               
// The 'which' argument contains the index position
               
// of the selected item
           
}
   
});
   
return builder.create();
}

목록은 대화상자의 콘텐츠 영역에 나타나므로, 대화상자는 메시지와 목록을 둘 다 표시할 수 없습니다. 대화상자에는 setTitle()로 제목을 설정해야 합니다. 목록에 대한 항목을 지정하려면 setItems()를 호출하여 배열을 하나 전달합니다. 아니면 setAdapter()를 사용하여 목록을 지정해도 됩니다. 이렇게 하면 동적인 데이터가 있는 목록(예: 데이터베이스에서 가져온 것)을 ListAdapter로 지원할 수 있게 해줍니다.

ListAdapter로 목록을 지원하기로 선택하는 경우, 항상 Loader를 사용해야 콘텐츠가 비동기식으로 로드됩니다. 이것은 어댑터로 레이아웃 구축로더 가이드에 더 자세히 설명되어 있습니다.

참고: 기본적으로 목록 항목을 터치하면 대화상자가 닫힙니다. 다만 다음과 같은 지속적 선택 목록 중 하나를 사용하는 경우는 예외입니다.




그림 4. 다중 선택 항목의 목록.

지속적 다중 선택 또는 단일 선택 목록 추가

다중 선택 항목 목록(체크박스)을 추가하거나 단일 선택 항목 목록(라디오 버튼)을 추가하려면, 각각 setMultiChoiceItems() 또는 setSingleChoiceItems() 메서드를 사용합니다.

예를 들어 다음은 그림 4에 표시된 것과 같이 다중 선택 목록을 생성하는 방법입니다. 이것은 선택한 항목을 ArrayList에 저장합니다.

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    mSelectedItems
= new ArrayList();  // Where we track the selected items
   
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
   
// Set the dialog title
    builder
.setTitle(R.string.pick_toppings)
   
// Specify the list array, the items to be selected by default (null for none),
   
// and the listener through which to receive callbacks when items are selected
           
.setMultiChoiceItems(R.array.toppings, null,
                     
new DialogInterface.OnMultiChoiceClickListener() {
               
@Override
               
public void onClick(DialogInterface dialog, int which,
                       
boolean isChecked) {
                   
if (isChecked) {
                       
// If the user checked the item, add it to the selected items
                       mSelectedItems
.add(which);
                   
} else if (mSelectedItems.contains(which)) {
                       
// Else, if the item is already in the array, remove it
                       mSelectedItems
.remove(Integer.valueOf(which));
                   
}
               
}
           
})
   
// Set the action buttons
           
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
               
@Override
               
public void onClick(DialogInterface dialog, int id) {
                   
// User clicked OK, so save the mSelectedItems results somewhere
                   
// or return them to the component that opened the dialog
                   
...
               
}
           
})
           
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
               
@Override
               
public void onClick(DialogInterface dialog, int id) {
                   
...
               
}
           
});

   
return builder.create();
}

일반적인 목록과 라디오 버튼이 있는 목록 양쪽 모두 '단일 선택' 작업을 제공하지만, 사용자의 선택을 유지하고자 하는 경우 setSingleChoiceItems()를 사용해야 합니다. 다시 말해, 대화상자를 나중에 다시 열 때 사용자의 현재 선택 항목이 무엇인지 나타내야 하는 경우 라디오 버튼 목록을 생성해야 합니다.

사용자 지정 레이아웃 생성



그림 5. 사용자 지정 대화상자 레이아웃.

대화상자에서 사용자 지정 레이아웃을 원하는 경우, 레이아웃을 생성한 다음 AlertDialog.Builder 객체에서 setView()를 호출하여 이를 AlertDialog에 추가합니다.

기본적으로 사용자 지정 레이아웃이 대화상자 창을 가득 채우지만, 여전히 AlertDialog.Builder 메서드를 사용하여 버튼과 제목을 추가할 수 있습니다.

예를 들어 다음은 그림 5에 표시된 대화상자에 대한 레이아웃 파일입니다.

res/layout/dialog_signin.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   
android:orientation="vertical"
   
android:layout_width="wrap_content"
   
android:layout_height="wrap_content">
   
<ImageView
       
android:src="@drawable/header_logo"
       
android:layout_width="match_parent"
       
android:layout_height="64dp"
       
android:scaleType="center"
       
android:background="#FFFFBB33"
       
android:contentDescription="@string/app_name" />
   
<EditText
       
android:id="@+id/username"
       
android:inputType="textEmailAddress"
       
android:layout_width="match_parent"
       
android:layout_height="wrap_content"
       
android:layout_marginTop="16dp"
       
android:layout_marginLeft="4dp"
       
android:layout_marginRight="4dp"
       
android:layout_marginBottom="4dp"
       
android:hint="@string/username" />
   
<EditText
       
android:id="@+id/password"
       
android:inputType="textPassword"
       
android:layout_width="match_parent"
       
android:layout_height="wrap_content"
       
android:layout_marginTop="4dp"
       
android:layout_marginLeft="4dp"
       
android:layout_marginRight="4dp"
       
android:layout_marginBottom="16dp"
       
android:fontFamily="sans-serif"
       
android:hint="@string/password"/>
</LinearLayout>

팁: 기본적으로 EditText 요소를 설정하여 "textPassword" 입력 유형을 사용하고자 하는 경우, 글꼴 모음이 고정 폭으로 설정되어 있으므로 글꼴 집합을 "sans-serif"로 변경해야 합니다. 그래야 양쪽 텍스트 필드가 모두 일치하는 글꼴 스타일을 사용할 수 있습니다.

DialogFragment 안의 레이아웃을 팽창시키려면, LayoutInflatergetLayoutInflater()로 가져와 inflate()를 호출합니다. 여기서 첫 번째 매개변수가 레이아웃 리소스 ID이고 두 번째 매개변수가 레이아웃의 상위 뷰입니다. 그런 다음 setView()를 호출하여 레이아웃을 대화상자에 배치할 수 있습니다.

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
   
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
   
// Get the layout inflater
   
LayoutInflater inflater = getActivity().getLayoutInflater();

   
// Inflate and set the layout for the dialog
   
// Pass null as the parent view because its going in the dialog layout
    builder
.setView(inflater.inflate(R.layout.dialog_signin, null))
   
// Add action buttons
           
.setPositiveButton(R.string.signin, new DialogInterface.OnClickListener() {
               
@Override
               
public void onClick(DialogInterface dialog, int id) {
                   
// sign in the user ...
               
}
           
})
           
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
               
public void onClick(DialogInterface dialog, int id) {
                   
LoginDialogFragment.this.getDialog().cancel();
               
}
           
});
   
return builder.create();
}

팁: 사용자 지정 대화상자를 원하는 경우, Dialog API를 사용하는 대신 Activity를 대화상자로 표시할 수 있습니다. 단순히 액티비티를 하나 생성한 다음 그 테마를 <activity> 매니페스트 요소에 있는 Theme.Holo.Dialog로 설정하면 됩니다.

<activity android:theme="@android:style/Theme.Holo.Dialog" >

이게 전부입니다. 이제 액티비티가 대화상자를 전체 화면이 아니라 대화상자 창으로 표시합니다.

이벤트를 대화상자의 호스트에 다시 전달


사용자가 대화상자의 작업 버튼 중 하나를 터치하거나 목록에서 항목을 하나 선택하면, DialogFragment가 필요한 작업을 알아서 수행할 수도 있지만 대부분의 경우 이벤트를 대화상자를 연 액티비티 또는 프래그먼트에 직접 전달하고자 할 수 있습니다. 이렇게 하려면 각 클릭 이벤트의 유형별로 메서드가 있는 인터페이스를 정의합니다. 그런 다음 해당 인터페이스를 대화상자로부터 작업 이벤트를 수신할 호스트 구성 요소에 구현하면 됩니다.

예를 들어 다음은 인터페이스를 정의하는 DialogFragment입니다. 이 인터페이스를 통해 이벤트를 호스트 액티비티에 도로 전달하게 됩니다.

public class NoticeDialogFragment extends DialogFragment {

   
/* The activity that creates an instance of this dialog fragment must
     * implement this interface in order to receive event callbacks.
     * Each method passes the DialogFragment in case the host needs to query it. */

   
public interface NoticeDialogListener {
       
public void onDialogPositiveClick(DialogFragment dialog);
       
public void onDialogNegativeClick(DialogFragment dialog);
   
}

   
// Use this instance of the interface to deliver action events
   
NoticeDialogListener mListener;

   
// Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
   
@Override
   
public void onAttach(Activity activity) {
       
super.onAttach(activity);
       
// Verify that the host activity implements the callback interface
       
try {
           
// Instantiate the NoticeDialogListener so we can send events to the host
            mListener
= (NoticeDialogListener) activity;
       
} catch (ClassCastException e) {
           
// The activity doesn't implement the interface, throw exception
           
throw new ClassCastException(activity.toString()
                   
+ " must implement NoticeDialogListener");
       
}
   
}
   
...
}

대화상자를 호스팅하는 액티비티는 대화상자 프래그먼트의 생성자를 사용하여 대화상자의 인스턴스를 생성하고 NoticeDialogListener 인터페이스 구현을 통해 대화상자의 이벤트를 수신합니다.

public class MainActivity extends FragmentActivity
                         
implements NoticeDialogFragment.NoticeDialogListener{
   
...

   
public void showNoticeDialog() {
       
// Create an instance of the dialog fragment and show it
       
DialogFragment dialog = new NoticeDialogFragment();
        dialog
.show(getSupportFragmentManager(), "NoticeDialogFragment");
   
}

   
// The dialog fragment receives a reference to this Activity through the
   
// Fragment.onAttach() callback, which it uses to call the following methods
   
// defined by the NoticeDialogFragment.NoticeDialogListener interface
   
@Override
   
public void onDialogPositiveClick(DialogFragment dialog) {
       
// User touched the dialog's positive button
       
...
   
}

   
@Override
   
public void onDialogNegativeClick(DialogFragment dialog) {
       
// User touched the dialog's negative button
       
...
   
}
}

호스트 액티비티는 위에 표시된 onAttach() 콜백 메서드에 의해 강제 적용되는 NoticeDialogListener를 구현하기 때문에 해당 대화상자 프래그먼트는 인터페이스 콜백 메서드를 사용하여 액티비티에 클릭 이벤트를 전달할 수 있습니다.

public class NoticeDialogFragment extends DialogFragment {
   
...

   
@Override
   
public Dialog onCreateDialog(Bundle savedInstanceState) {
       
// Build the dialog and set up the button click handlers
       
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder
.setMessage(R.string.dialog_fire_missiles)
               
.setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
                   
public void onClick(DialogInterface dialog, int id) {
                       
// Send the positive button event back to the host activity
                       mListener
.onDialogPositiveClick(NoticeDialogFragment.this);
                   
}
               
})
               
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                   
public void onClick(DialogInterface dialog, int id) {
                       
// Send the negative button event back to the host activity
                       mListener
.onDialogNegativeClick(NoticeDialogFragment.this);
                   
}
               
});
       
return builder.create();
   
}
}

대화상자 표시


대화상자를 표시하고자 하는 경우, DialogFragment의 인스턴스를 생성한 다음 FragmentManager와 대화상자 프래그먼트에 대한 태그 이름을 전달하여 show()를 호출합니다.

FragmentManager를 가져오려면 FragmentActivity에서 getSupportFragmentManager()를 호출하거나 Fragment에서 getFragmentManager()를 호출합니다. 예:

public void confirmFireMissiles() {
   
DialogFragment newFragment = new FireMissilesDialogFragment();
    newFragment
.show(getSupportFragmentManager(), "missiles");
}

두 번째 인수 "missiles"는 시스템이 필요에 따라 프래그먼트의 상태를 저장하고 복원하는 데 사용하는 고유한 태그 이름입니다. 이 태그를 사용하면 findFragmentByTag()를 호출하여 해당 프래그먼트를 파악할 수도 있습니다.

대화상자를 전체 화면으로 또는 내장 프래그먼트로 표시


UI 디자인에서, 몇몇 상황 하에서는 UI의 한 조각을 대화상자로 나타내지만 다른 상황에서는 전체 화면이나 포함된 프래그먼트로 나타내고자 하는 경우가 있을 수 있습니다(이는 어쩌면 기기 화면이 대형인지 소형인지에 따라 달라질 수도 있습니다). DialogFragment 클래스에서 이런 유연성을 제공하는 것은 이것이 여전히 포함 가능한 Fragment 역할을 할 수 있기 때문입니다.

그러나 이 경우에는 대화상자를 빌드하는 데 AlertDialog.Builder 또는 다른 Dialog 객체를 사용하면 안 됩니다. DialogFragment를 포함 가능한 상태로 만들려면, 레이아웃 안에 있는 대화상자의 UI를 정의해야 합니다. 그런 다음 레이아웃을 onCreateView() 콜백에 로드합니다.

다음은 대화상자 또는 포함 가능한 프래그먼트 중 어느 쪽으로든 표시될 수 있는 DialogFragment 예시입니다(purchase_items.xml이라는 레이아웃 사용).

public class CustomDialogFragment extends DialogFragment {
   
/** The system calls this to get the DialogFragment's layout, regardless
        of whether it's being displayed as a dialog or an embedded fragment. */

   
@Override
   
public View onCreateView(LayoutInflater inflater, ViewGroup container,
           
Bundle savedInstanceState) {
       
// Inflate the layout to use as dialog or embedded fragment
       
return inflater.inflate(R.layout.purchase_items, container, false);
   
}

   
/** The system calls this only when creating the layout in a dialog. */
   
@Override
   
public Dialog onCreateDialog(Bundle savedInstanceState) {
       
// The only reason you might override this method when using onCreateView() is
       
// to modify any dialog characteristics. For example, the dialog includes a
       
// title by default, but your custom layout might not need it. So here you can
       
// remove the dialog title, but you must call the superclass to get the Dialog.
       
Dialog dialog = super.onCreateDialog(savedInstanceState);
        dialog
.requestWindowFeature(Window.FEATURE_NO_TITLE);
       
return dialog;
   
}
}

그리고 다음은 프래그먼트를 대화상자로 표시할지 전체 화면 UI로 표시할지 화면 크기를 근거로 결정하는 몇 가지 코드입니다.

public void showDialog() {
   
FragmentManager fragmentManager = getSupportFragmentManager();
   
CustomDialogFragment newFragment = new CustomDialogFragment();

   
if (mIsLargeLayout) {
       
// The device is using a large layout, so show the fragment as a dialog
        newFragment
.show(fragmentManager, "dialog");
   
} else {
       
// The device is smaller, so show the fragment fullscreen
       
FragmentTransaction transaction = fragmentManager.beginTransaction();
       
// For a little polish, specify a transition animation
        transaction
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
       
// To make it fullscreen, use the 'content' root view as the container
       
// for the fragment, which is always the root view for the activity
        transaction
.add(android.R.id.content, newFragment)
                   
.addToBackStack(null).commit();
   
}
}

프래그먼트 트랜잭션 수행에 대한 자세한 내용은 프래그먼트 가이드를 참조하세요.

이 예시에서 mIsLargeLayout 부울은 현재 기기가 앱의 큰 레이아웃 디자인을 사용해야 하는지 여부를 지정합니다(따라서 이 프래그먼트를 전체 화면이 아니라 대화상자로 표시합니다). 이런 종류의 부울을 설정하는 가장 좋은 방법은 부울 리소스 값을 여러 가지 화면 크기에 대한 대체 리소스 값으로 선언하는 것입니다. 예를 들어 다음은 여러 가지 화면 크기에 대한 두 가지 버전의 부울 리소스입니다.

res/values/bools.xml

<!-- Default boolean values -->
<resources>
   
<bool name="large_layout">false</bool>
</resources>

res/values-large/bools.xml

<!-- Large screen boolean values -->
<resources>
   
<bool name="large_layout">true</bool>
</resources>

그러면 액티비티의 onCreate() 메서드 중에 mIsLargeLayout 값을 초기화할 수 있습니다.

boolean mIsLargeLayout;

@Override
public void onCreate(Bundle savedInstanceState) {
   
super.onCreate(savedInstanceState);
    setContentView
(R.layout.activity_main);

    mIsLargeLayout
= getResources().getBoolean(R.bool.large_layout);
}

액티비티를 큰 화면에 대화상자로 표시

작은 화면의 경우 대화상자를 전체 화면 UI로 표시하는 대신, 큰 화면에 있을 때에는 Activity를 대화상자로 표시함으로써 같은 결과를 얻을 수 있습니다. 어느 방식을 사용할 것인지는 앱 디자인에 따라 달라지지만, 액티비티를 대화상자로 표시하면 앱이 이미 작은 화면용으로 디자인된 상태에서 태블릿에서의 환경을 개선하기 위해 일시적인 액티비티를 대화상자로 표시하는 경우 유용할 때가 많습니다.

큰 화면의 경우 액티비티를 대화상자로만 표시하려면, Theme.Holo.DialogWhenLarge 테마를 <activity> 매니페스트 요소에 적용하면 됩니다.

<activity android:theme="@android:style/Theme.Holo.DialogWhenLarge" >

액티비티를 여러 가지 테마로 스타일링하는 법에 대한 자세한 정보는 스타일 및 테마 가이드를 참조하세요.

대화상자 닫기


사용자가 AlertDialog.Builder로 생성한 작업 버튼 중 하나라도 터치하면 시스템이 대화상자를 대신 닫습니다.

시스템은 사용자가 대화상자 목록에서 항목을 터치하는 경우에도 대화상자를 닫습니다. 다만 목록이 라디오 버튼이나 체크박스를 사용하는 경우에는 예외입니다. 그렇지 않으면 대화상자를 수동으로 닫을 수도 있습니다. DialogFragment에서 dismiss()를 호출하면 됩니다.

대화상자가 사라질 때 특정 작업을 수행해야 하는 경우, DialogFragment에서 onDismiss() 메서드를 구현하면 됩니다.

또한 대화상자를 취소할 수도 있습니다. 이것은 사용자가 작업을 완료하지 않고 대화상자를 분명히 떠났다는 것을 나타내는 특수 이벤트입니다. 이것은 사용자가 Back 버튼을 누르거나 대화상자 영역 바깥의 화면을 터치하거나, 개발자가 Dialog에서 명시적으로 cancel()을 호출(예: 대화상자의 'Cancel' 버튼에 대한 응답으로)한 경우 발생합니다.

위의 예시에 나타난 바와 같이 취소 이벤트에 응답하려면 DialogFragment 클래스에서 onCancel()을 구현하면 됩니다.

참고: 시스템은 onCancel() 콜백을 불러오는 이벤트가 발생할 때마다 onDismiss()를 호출합니다. 그러나 Dialog.dismiss() 또는 DialogFragment.dismiss()를 호출하면 시스템이 onDismiss()를 호출하되, onCancel()은 호출하지 않습니다. 따라서 사용자가 대화상자를 뷰에서 제거하기 위해 대화상자에 있는 긍정적인 버튼을 누르는 경우, 일반적으로 dismiss()를 사용해야 합니다.



작성자

Posted by 드리머즈

관련 글

댓글 영역