http://blog.naver.com/aiger?Redirect=Log&logNo=100149726744


안드로이드는 Dialog와 Toast 두 개로 메시지창을 많이 띄웁니다.

그중에 많이 쓰이는게 Dialog죠.

이렇게 쓰면 좀 더 편하지 않을까 해서 샘플 소스 올려봅니다.

 

1. onCreateDialog

: dialog 생성할때 많이 오버라이드해서 쓰실거라 생각됩니다. 한 함수내에서 다이얼로그를 관리할 수 있다는 면에선 좋지만 단점이 존재하죠.

로그를 찍어보시면 아시겠지만, 한번 onCreateDialog로 생성된 다이얼로그는 다시 onCreateDialog를 타지 않습니다. 한번 생성이 되면 액티비티안에서 관리가 되는걸로 보여집니다. DatePickerDialog를 onCreateDialog안에서 생성해 보시면 생성된 후 날짜를 변경하고 다시 showDialog시키면 이전에 변경된 날짜로 표시되는걸 확인하실 수 있습니다.

다시 쓰지 않는 다이얼로그는 아래와 같이 설정해서 삭제해줘야 합니다.

@Override
 protected void onPrepareDialog(int id, Dialog dialog) {
     // TODO Auto-generated method stub 
     super.onPrepareDialog(id, dialog);
     switch (id) {
          case //해당 다이얼로그 id

               removeDialog(id);
        }
   }
 

2. OnDismissListener

: 액티비티의 onCreateDialog로 다이얼로그 객체를 만드는 부분은 모을 수 있지만, 다이얼로그마다 ok버튼리스너, cancel버튼리스너를 다이얼로그마다 설정해야 하는 번거로움이 있습니다.

그럴때 사용하면 유용한게 OnDismissListener입니다.

dialog를 상속받은 클래스를 만든 후

private OnDismissListener mConfirmListener = null;

public ConfirmMsgDialog(Context context, CharSequence message, OnDismissListener confirmListener) {
  super(context, R.style.theme_Dialog); //theme는 Style로 지정
struct(context);
  setMessage(message);
  mConfirmListener = confirmListener; 
 }

 

private void construct(Context context) {

//커스톰이 아닐시 리스너만 전달

  if (mConfirmListener != null) {

      setOnDismissListener(mConfirmListener);

}

  dismiss();

setContentView(R.layout.confirm_msg_dialog); //커스톰이라면 layout을 변경
  ((TextView) findViewById(android.R.id.title)).setVisibility(View.GONE);  //타이틀 미표시

  Button button;
  button = (Button) findViewById(R.id.ok); //커스톰일 경우 해당 ok버튼을 클릭시 dismissListener호출
  button.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    if (mConfirmListener != null) {
     setOnDismissListener(mConfirmListener);
    }
    dismiss();
   }
  });
 }

 

그리고 액티비티내에서 다이얼로그를 호출시 new ConfirmMsgDialog(context, "메시지", okListener);

private OnDismissListener okListener= new OnDismissListener() {

  @Override
  public void onDismiss(DialogInterface dialog) {

         //확인버튼 누를시 실행할 코드
     }
 };

 

okListener는 다른 다이얼로그에도 적용이 가능하므로 재활용할 수 있습니다.

 

//백키와 메뉴롱키도 막게 할 수 있습니다. (메뉴롱키를 누르면 다이얼로그가 사라집니다) 프로그레스바처럼 뭔가를 실행중일때 프로그레스다이얼로그만 사라지는 사태가 생기면 안되겠죠~

public void backKeyLongKeyBlock()
 {
  this.setOnCancelListener(new OnCancelListener(){
   @Override
   public void onCancel(DialogInterface dialog) {
    // TODO Auto-generated method stub
    
   }
  });
  
  this.setOnKeyListener(new OnKeyListener() {
   
   @Override
   public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
    // TODO Auto-generated method stub    
    switch (keyCode) {
    case KeyEvent.KEYCODE_MENU:
     if(event.isLongPress())
     {
      return true;
     }
     break;
    }
    return false;
   }
  });
 }

 

3. window leap 에러

: 다이얼로그를 쓰다보면 자주 발생하는 ANR - window leap에러입니다. 다이얼로그가 액티비티에 종속적이기 때문에 발생하는 걸로 생각됩니다.

발생하는 이유는 다이얼로그가 떠 있는 상태에서 액티비티가 종료될 경우 발생하죠.

해당 액티비티가 종료되는 시점 onDestroy함수에서 해당 다이얼로그를 dismiss()시켜야 발생하지 않습니다.