Android QQ 메시지 알림 을 모방 하여 팝 업 대화 상자 구현

본 고 는 이 글 의 기초 에서 학습 하고 구체 적 인 내용 은 다음 과 같다.
1.개술
안 드 로 이 드 네 이 티 브 컨트롤 은 추 하기 로 유명 하기 때문에 거의 모든 응용 프로그램 이 자신의 UI 스타일 을 특별히 맞 춥 니 다.그 중에서 팝 업 알림 상자 의 맞 춤 형 제작 은 특히 흔히 볼 수 있 습 니 다.이 편 은 QQ 종료 알림 상 자 를 모방 하여 흔히 볼 수 있 는 몇 가지 사용자 정의 알림 상자 의 실현 방식 을 살 펴 보 겠 습 니 다.
여기 서 사용 하 는 몇 가지 팝 업 상자 의 실현 방법 은 다음 과 같은 몇 가지 로 요약 된다.
사용자 정의 대화 상자
사용자 정의 PopupWindow
사용자 정의 레이아웃 보기
Activity 의 Dialog 스타일
FragmentDialog
최종 효과 도 를 먼저 보 세 요:

2.실천
앞에서 언급 한 몇 가지 실현 방식 은 모두 같은 시연 효 과 를 거 둘 수 있 지만 그 중에서 도 각각 다르다.여기 서 먼저 각종 구체 적 인 실현 을 하나하나 열거 하고 마지막 으로 종합 적 으로 정리 하고 귀납 합 시다.
그 전에 여기 서 이 루어 진 대화 상자 공용 레이아웃 layot/confirm 을 살 펴 보 겠 습 니 다.dialog.xml 。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_marginLeft="5dp"
 android:layout_marginRight="5dp"
 android:background="@drawable/confirm_dialog_bg"
 android:orientation="vertical">

 <LinearLayout
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:background="@android:color/transparent"
  android:orientation="vertical" >

  <TextView
   android:id="@+id/title_name"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:gravity="center_horizontal"
   android:paddingBottom="10dp"
   android:paddingTop="15dp"
   android:text="Message Title"
    android:textColor="@android:color/black"
   android:textSize="20sp"
   android:visibility="visible" />
 </LinearLayout>

 <LinearLayout
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:background="@android:color/transparent"
  android:orientation="vertical" >

  <TextView 
   android:id="@+id/text_view"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:layout_marginLeft="15dp"
   android:layout_marginRight="15dp"
   android:layout_marginTop="10dp"
   android:textColor="@android:color/black"
   android:text="this is message content"
   android:textSize="16dip"/>

  <View
   android:layout_width="match_parent"
   android:layout_height="1px"
   android:layout_marginTop="15dip"
   android:background="#c5c5c5" />

  <LinearLayout
   android:layout_width="fill_parent"
   android:layout_height="50dip"
   android:background="@android:color/transparent"
   android:gravity="center_horizontal"
   android:orientation="horizontal" >

   <!--      -->
   <Button
    android:id="@+id/btn_cancel"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:text="Cancel"
    android:textStyle="bold"
    android:textColor="#0072c6"
    android:background="@drawable/confirm_dialog_cancel_selector"
    android:textSize="15sp" />

   <!--      -->

   <View 
    android:layout_width="1px"
    android:layout_height="match_parent"
    android:layout_gravity="center_horizontal"
    android:background="#c5c5c5"/>

   <Button
    android:id="@+id/btn_ok"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:text="OK"
    android:textStyle="bold"
    android:textColor="#0072c6"
    android:background="@drawable/confirm_dialog_ok_selector"
    android:textSize="15sp" />
  </LinearLayout>
 </LinearLayout>

</LinearLayout>

레이아웃 미리 보기 만으로 효 과 를 볼 수 있 습 니 다:

아래 에서 우 리 는 각각 상술 한 몇 가지 방식 을 통 해 이 레이아웃 을 사용 하여 메시지 알림 상 자 를 보 여 줍 니 다.  
2.1 Dialog 
이것 은 가장 기본 적 이 고 가장 흔히 볼 수 있 는 비 차단 식 대화 상자 입 니 다.구체 적 인 형식 은 7 가지 로 나 눌 수 있 는데 인터넷 의 각종 문장 을 상세 하 게 참조 하고 한 편 을 마음대로 인용 할 수 있다7 가지 형식의 Android Dialog 사용 실례
(비고:공식 적 으로 fragment Dialog 가 출시 된 후 Dialog 를 사용 하여 대화 상 자 를 만 드 는 것 을 추천 하지 않 습 니 다.이것 은 뒷말 입 니 다)
여기 서 사용자 정의 알림 상자 ConfirmDialog 는 Dialog 에서 계승 하여 confirm 을 사용 합 니 다.dialog.xml 레이아웃 을 초기 화하 고 이벤트 에 연결 합 니 다.

public class ConfirmDialog extends Dialog {
 private Context context;
 private TextView titleTv,contentTv;
 private View okBtn,cancelBtn;
 private OnDialogClickListener dialogClickListener;

 public ConfirmDialog(Context context) {
  super(context);
  this.context = context;
  initalize();
 }

 //   View
 private void initalize() {
  LayoutInflater inflater = LayoutInflater.from(context);
  View view = inflater.inflate(R.layout.confirm_dialog, null);
  setContentView(view);
  initWindow();

  titleTv = (TextView) findViewById(R.id.title_name);
  contentTv = (TextView) findViewById(R.id.text_view);
  okBtn = findViewById(R.id.btn_ok);
  cancelBtn = findViewById(R.id.btn_cancel);
  okBtn.setOnClickListener(new View.OnClickListener() {

   @Override
   public void onClick(View v) {
    dismiss();
    if(dialogClickListener != null){
     dialogClickListener.onOKClick();
    }
   }
  });
  cancelBtn.setOnClickListener(new View.OnClickListener() {

   @Override
   public void onClick(View v) {
    dismiss();
    if(dialogClickListener != null){
     dialogClickListener.onCancelClick();
    }
   }
  });
 }

 /**
 *         
 */
 private void initWindow() {
  Window dialogWindow = getWindow();
  dialogWindow.setBackgroundDrawable(new ColorDrawable(0));//  window  
  dialogWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);//         
  WindowManager.LayoutParams lp = dialogWindow.getAttributes();
  DisplayMetrics d = context.getResources().getDisplayMetrics();//      
  lp.width = (int) (d.widthPixels * 0.8); //     80% 
  lp.gravity = Gravity.CENTER;  //    
  dialogWindow.setAttributes(lp);
 }

 public void setOnDialogClickListener(OnDialogClickListener clickListener){
  dialogClickListener = clickListener;
 }

 /**
 *        
 */
 public interface OnDialogClickListener{
  void onOKClick();
  void onCancelClick();
 }
}

2.2 PopupWindow 
PopupWindow 는 차단 식 대화 상자 로 작업 을 종료 할 때 만 프로그램 이 계속 실 행 됩 니 다.또한 팝 윈도 우 는 자유 에 따라 자신의 위 치 를 정할 수 있다.위치 에 따라 오프셋 이 있 는 지 없 는 지 에 따라 오프셋 과 무 오프셋 두 가지 로 나 눌 수 있다.참고 물 에 따라 특정한 컨트롤(Anchor 닻)과 부모 에 대한 컨트롤 로 나 눌 수 있 습 니 다.구체 적 으로 다음 과 같다.
showAsDropDown(View anchor):특정한 컨트롤 의 위치(왼쪽 아래)에 비해 오프셋 이 없습니다.
showAsDropDown(View anchor,int xoff,int yoff):특정한 컨트롤 의 위치(바로 아래)에 비해 오프셋 이 있 습 니 다.
showAtLocation(View parent,int gravity,int x,int y):부모 컨트롤 의 위치(예 를 들 어 중앙 Gravity.CENTER,아래 Gravity.BOTTOM 등)에 비해 오프셋 이나 오프셋 없 음 을 설정 할 수 있 습 니 다.
여 기 는 똑 같은 디 스 플레이 효 과 를 얻 었 을 뿐 쇼 AtBottom 의 사용 만 시범 적 으로 보 여 줍 니 다.

public class ConfirmPopWindow extends PopupWindow{
 private Context context;
 private TextView titleTv,contentTv;
 private View okBtn,cancelBtn;
 private OnDialogClickListener dialogClickListener;

 public ConfirmPopWindow(Context context) {
  super(context);
  this.context = context;
  initalize();
 }

 private void initalize() {
  LayoutInflater inflater = LayoutInflater.from(context);
  View view = inflater.inflate(R.layout.confirm_dialog, null);
  setContentView(view);
  initWindow();

  titleTv = (TextView) view.findViewById(R.id.title_name);
  contentTv = (TextView) view.findViewById(R.id.text_view);
  okBtn = view.findViewById(R.id.btn_ok);
  cancelBtn = view.findViewById(R.id.btn_cancel);
  okBtn.setOnClickListener(new View.OnClickListener() {

   @Override
   public void onClick(View v) {
    dismiss();
    if(dialogClickListener != null){
     dialogClickListener.onOKClick();
    }
   }
  });
  cancelBtn.setOnClickListener(new View.OnClickListener() {

   @Override
   public void onClick(View v) {
    dismiss();
    if(dialogClickListener != null){
     dialogClickListener.onCancelClick();
    }
   }
  });
 }

 private void initWindow() {
  this.setBackgroundDrawable(new ColorDrawable(0)); 
  DisplayMetrics d = context.getResources().getDisplayMetrics();
  this.setWidth((int) (d.widthPixels * 0.8)); 
  this.setHeight(LayoutParams.WRAP_CONTENT); 
  this.setFocusable(true); 
  this.setOutsideTouchable(true); 
  this.update(); 
 }

 public void showAtBottom(View view){
  showAsDropDown(view, Math.abs((view.getWidth() - getWidth())/2), 20);
 }

 public void setOnDialogClickListener(OnDialogClickListener clickListener){
  dialogClickListener = clickListener;
 }

 public interface OnDialogClickListener{
  void onOKClick();
  void onCancelClick();
 }
}

2.3 사용자 정의 레이아웃
앞의 두 가 지 는 시스템 에 포 장 된 View 입 니 다.마찬가지 로 레이아웃 레이아웃 을 사용자 정의 하여 팝 업 대화 상자 효 과 를 낼 수 있 습 니 다.사용자 정의 인 만큼 꼼꼼 히 말씀 드 려 야 합 니 다.
ConfirmLayout 는 FrameLayout 에서 계승 하여 창 관리자 WindowManager 를 가 져 와 사용자 정의 view 를 창 맨 앞 에 추가 하고 표시 하여 예상 효 과 를 얻 습 니 다.    
1.뷰 초기 화
반투명 검은색 배경 과 대응 하 는 confirm 초기 화layot,그리고 창 에 버튼 을 추가 하여 이 벤트 를 되 돌려 줍 니 다.

 protected void initialize() {
  initBackground();//       
  initContentView();//   confirm_layout    View

  windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
  setOnKeyListener(new OnKeyListener() { //        
   @Override
   public boolean onKey(View v, int keyCode, KeyEvent event) {
    if (KeyEvent.KEYCODE_BACK == keyCode && KeyEvent.ACTION_DOWN == event.getAction()) {
     hide();//    view
     return true;
    }
    return false;
   }

  setFocusable(true); //     
  setFocusableInTouchMode(true); //       
 }

2.사용자 정의 보기:show()
디 스 플레이 를 호출 할 때 메 인 스 레 드 에 현재 View 가 창 에 추가 되 지 않 으 면 추가 합 니 다.그 다음 에 애니메이션 그 라 데 이 션 효 과 를 사용 하여 배경 을 표시 하고 마지막 으로 애니메이션 이 완 료 될 때 현재 대화 상자 보 기 를 표시 합 니 다.

public void show() {
  ((Activity) getContext()).runOnUiThread(new Runnable() {
   @Override
   public void run() {
    if (getParent() == null) { //          
     //         ,       ,     
     WindowManager.LayoutParams wlp = new WindowManager.LayoutParams();
     wlp.type = WindowManager.LayoutParams.TYPE_APPLICATION;
     wlp.format = PixelFormat.TRANSPARENT;
     wlp.gravity = Gravity.LEFT | Gravity.TOP;
     wlp.width = LayoutParams.MATCH_PARENT;
     wlp.height = LayoutParams.MATCH_PARENT;
     windowManager.addView(ConfirmLayout.this, wlp);
    }
    showBackGround();//          View
   }
  });
 }

 /**
 *      
 */
 protected void showBackGround() {
  if (isShowing)
   return;
  isShowing = true;
  background.clearAnimation();
  background.setVisibility(View.VISIBLE);
  AlphaAnimation an = new AlphaAnimation(0, 1);
  an.setDuration(durationMillis);
  background.startAnimation(an);
 }

3.사용자 정의 숨 기기 VIEW:hide()
대화 상 자 를 숨 기 는 방법 은 show()와 정반 대 입 니 다.먼저 숨겨 진 애니메이션 을 호출 하고 애니메이션 이 끝나 면 창 에서 View 를 제거 합 니 다.

 public void hide() {
  ((Activity) getContext()).runOnUiThread(new Runnable() {
   @Override
   public void run() {
    hideBackGround();//    
    if (getParent() != null)
     windowManager.removeView(ConfirmLayout.this);//  view
   }
  });
 }

 /**
 *        
 */
 protected void hideBackGround() {
  if (!isShowing)
   return;
  isShowing = false;
  background.clearAnimation();
  AlphaAnimation an = new AlphaAnimation(1, 0);
  an.setDuration(durationMillis);
  an.setAnimationListener(new AnimationListener() {
   @Override
   public void onAnimationStart(Animation animation) {
   }

   @Override
   public void onAnimationRepeat(Animation animation) {
   }

   @Override
   public void onAnimationEnd(Animation animation) {
    background.setVisibility(View.GONE);
   }
  });
  background.startAnimation(an);
 }

다른 부분 은 위 와 같이 일일이 붙 이지 않 고 예제 소스 코드 를 자세히 볼 수 있 습 니 다.  
2.4 Activity 의 Dialog 스타일
테마 Theme 을 사용 하여 Activity 를 dialog 로 표시 하 는 효 과 를 실현 합 니 다.우선 AndroidManifest.xml 에 이 activity 를 설정 하여
android:theme=”@android:style/Theme.Dialog”
마찬가지 로 우 리 는 Theme.Dialog 에 계승 되 는 style 스타일 을 사용자 정의 하여 사용자 정의 속성 을 추가 할 수 있 습 니 다.예 를 들 어:

<resources>
 <style name="DialogStyle" parent="@android:style/Theme.Dialog">
  <item name="android:windowBackground">@android:color/transparent</item>
  <item name="android:windowFrame">@null</item>
  <item name="android:windowNoTitle">true</item>
  <item name="android:windowIsFloating">true</item>
  <item name="android:windowIsTranslucent">true</item>
  <item name="android:windowFullscreen">true</item>
  <item name="android:backgroundDimEnabled">true</item>
 </style>
</resources>

그리고>android:theme="@style/DialogStyle"을 사용 하여 상기 효 과 를 얻 습 니 다.구체 적 인 실현 은 dialog 와 유사 합 니 다.

public class ConfirmActivity extends Activity{
 private TextView titleTv,contentTv;
 private View okBtn,cancelBtn;
 private OnDialogClickListener dialogClickListener;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  requestWindowFeature(Window.FEATURE_NO_TITLE);
  setContentView(R.layout.confirm_dialog);
  initViews();
  initListeners();
 }

 private void initViews() {
  initWindow();
  titleTv = (TextView) findViewById(R.id.title_name);
  contentTv = (TextView) findViewById(R.id.text_view);
  okBtn = findViewById(R.id.btn_ok);
  cancelBtn = findViewById(R.id.btn_cancel);
  okBtn.setOnClickListener(new View.OnClickListener() {

   @Override
   public void onClick(View v) {
    finish();
    if(dialogClickListener != null){
     dialogClickListener.onOKClick();
    }
   }
  });
 }

 private void initWindow() {
  getWindow().setBackgroundDrawable(new ColorDrawable(0));
  getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN |
    WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
 }

 private void initListeners() {
  cancelBtn.setOnClickListener(new View.OnClickListener() {

   @Override
   public void onClick(View v) {
    finish();
    if(dialogClickListener != null){
     dialogClickListener.onCancelClick();
    }
   }
  });
 }

 public void setOnDialogClickListener(OnDialogClickListener clickListener){
  dialogClickListener = clickListener;
 }


 public interface OnDialogClickListener{
  void onOKClick();
  void onCancelClick();
 }
}

2.5 DialogFragment 
DialogFragment 는 안 드 로 이 드 3.0 에 도입 되 어 홍보 되 었 습 니 다.
우 리 는 DialogFragment 를 사용 할 때,적어도 onCreate View 나 onCreate DIalog 방법 을 실현 해 야 한다.이 프 래 그 먼 트 는 onCreateDIalog 에서 앞에서 작성 한 ConfirmDialog 로 되 돌아 갑 니 다.

public class ConfirmFragment extends DialogFragment{

 @Override
 @NonNull
 public Dialog onCreateDialog(Bundle savedInstanceState) {
  return new ConfirmDialog(getActivity());
 }

public void setOnDialogClickListener(OnDialogClickListener clickListener){
  ((ConfirmDialog)getDialog()).setOnDialogClickListener(clickListener);
 }
}

물론 게 으 름 피 우 고 앞 에 정 의 된 Confirm Dialog 로 돌아 가 는 것 은 추천 하지 않 습 니 다.우 리 는 실제로 fragment 의 onCreate View 를 사용 하 는 것 도 더욱 합 리 적 이 고 소개 합 니 다.그 는 같은 Dialog 효 과 를 낼 수 있 으 며 내장 fragment 로 참조 할 수 있 습 니 다.사용 정 리 를 보면 Fragment Dialog 는 Dialog 에 비해 두 가지 장점 이 있다.
핸드폰 설정 이 바 뀌 어 Activity 를 다시 만들어 야 할 때,예 를 들 어 회전 화면,DialogFragment 대화 상 자 는 Fragment Manager 에서 자동 으로 재 구성 되 지만,Dialog 에서 실 현 된 대화 상 자 는 다시 생 성 되 지 않 습 니 다.
DialogFragment 는 fragment 의 장점 도 가지 고 있 습 니 다.즉,하나의 Activity 내부 에서 반환 을 실현 할 수 있 습 니 다.(Fragment Manager 는 반환 스 택 을 관리 하기 때 문 입 니 다.또한 그 는 일반 Fragment 로 다른 레이아웃 에 직접 끼 워 넣 을 수 있 습 니 다.
3.소결
실현 효 과 를 보면 우 리 는 확실히 많은 선택 이 있다.물론 우리 가 가장 많이 사용 하 는 것 은 반드시 Dialog(Fragment Dialog)와 PopupWindow 이다.그러나 일반적인 상황 에서 Dialog 와 PopupWindow 를 선택 하 는 것 은 우리 의 구체 적 인 사용 장면 에 의 해 결정 된다.예 를 들 어 일부 알림 메시지 가 Dialog 에 적합 하고 구체 적 인 옵션 이 팝 업 되 며 선택 결 과 를 기 다 려 야 하 는 경우 등 이 있 으 며 PopupWindow 를 사용 하 는 경향 이 있 습 니 다.
Fragment Dialog 의 몇 가지 사용 장면
  
PopupWindow 의 몇 가지 사용 장면
  
4.보충
사실 팝 업 메뉴 를 길 게 누 르 는 것 도 있 습 니 다.이 는 상기 방법 으로 메뉴 옵션 을 팝 업 할 수 있 을 뿐만 아니 라 시스템 에서 제공 하 는 View.setOnCreate ContextMenu()방법 으로 도 가능 합 니 다.예 를 들 면:

itemView.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
     menu.add("  ").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
      @Override
      public boolean onMenuItemClick(MenuItem item) {
       //      
       return true;
      }
     });
    }
   });

팝 업 을 길 게 누 르 면 기본 효 과 는:

관심 있 는 것 은 한번 해 보 세 요.
뒤쪽 으로 는 소스 코드 측면 에서 여기 서 말 하 는 몇 가지 실현 방안 의 구체 적 인 원 리 를 살 펴 보고 마지막 으로 간단 한 패 키 징 을 통 해 IOS 와 유사 한 Action Sheet 컨트롤 의 효 과 를 만 듭 니 다.
데모 효 과 는 다음 과 같 습 니 다.
  
자세 한 내용 은 다음 박문 에 계속 관심 을 가 져 주 십시오.
마지막 으로 본 편 에서 말 한 내용 의 소스 코드 를 동봉 합 니 다7 가지 형식의 Android Dialog 사용 예시(다시 업데이트 되 었 습 니 다)
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기