1. 程式人生 > 實用技巧 >中級實訓Android學習記錄——自定義Dialog、PopupWindow

中級實訓Android學習記錄——自定義Dialog、PopupWindow

學習記錄 2020/11/23

自定義Dialog

  • 自定義layout來存放dialog:layout_custom_dialog.xml

定義了兩個TextView來存放文字,兩個TextView用作按鈕的說明文字

  • 我們建立CustomDialog類,並繼承Dialog類

    • 建立初始化方法
    public CustomDialog(Context context) {
     super(context);
    }
    
    public CustomDialog(Context context, int themeId) {
     super(context, themeId);
    }
    

    第一個初始化方法接收一個context,第二個初始化方法接收一個context和一個themeId(目前不知道有啥用)

    • 為layout中每個TextView建立一個string物件和一個TextView物件,string存放他們的文字,為每個string物件構造一個setter
    public CustomDialog setTitle(String title) {
     this.title = title;
     return this;
    }
    
    public CustomDialog setMessage(String message) {
     this.message = message;
     return this;
    }
    
    public CustomDialog setConfirm(String confirm, IOnConfirmListener confirmListener) {
     this.confirm = confirm;
     this.confirmListener = confirmListener;
     return this;
    }
    
    public CustomDialog setCancel(String cancel, IOnCancelListener cancelListener) {
     this.cancel = cancel;
     this.cancelListener = cancelListener;
     return this;
    }
    

    為了能夠實現一連串的連續呼叫,我們宣告返回型別為CustomDialog並在每個setter中都返回this

    • 宣告兩個按鈕的Listener介面
    public interface  IOnCancelListener {
     void OnCancel(CustomDialog dialog);
    }
    
    public interface  IOnConfirmListener {
     void OnConfirm(CustomDialog dialog);
    }
    
    • 將CustomDialog類實現View.OnClickListener並覆蓋其onClick函式
    public class CustomDialog extends Dialog implements View.OnClickListener {
     @Override
     public void onClick(View v) {
         switch (v.getId()) {
             case R.id.tv_confirm:
                 if (this.confirmListener != null)
                     confirmListener.OnConfirm(this);
                 break;
             case R.id.tv_cancel:
                 if (this.cancelListener != null)
                     cancelListener.OnCancel(this);
                 break;
         }
     }
    }
    

    通過override他的onClick函式來達到我們點選事件的目的

    • 實現onCreate函式,主要進行視窗的初始化和變數的初始化
    @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.layout_custom_dialog);
         // 設定dialog寬度
         WindowManager manager = getWindow().getWindowManager();
         Display display = getContext().getDisplay();
         WindowManager.LayoutParams p = getWindow().getAttributes();
         Rect size = new Rect();
         size = manager.getCurrentWindowMetrics().getBounds();
         p.width = (int)((size.right - size.left) * 0.8);
         getWindow().setAttributes(p);
         // 讓圓角設定有效
         getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
    
         mtv_title = findViewById(R.id.tv_title);
         if (!TextUtils.isEmpty(title)) {
             mtv_title.setText(title);
         }
    
         mtv_Message = findViewById(R.id.tv_message);
         if (!TextUtils.isEmpty(message)) {
             mtv_Message.setText(message);
         }
    
         mtv_confirm = findViewById(R.id.tv_confirm);
         if (!TextUtils.isEmpty(confirm)) {
             mtv_confirm.setText(confirm);
         }
         mtv_confirm.setOnClickListener((View.OnClickListener) this);
    
         mtv_cancel = findViewById(R.id.tv_cancel);
         if (!TextUtils.isEmpty(cancel)) {
             mtv_cancel.setText(cancel);
         }
         mtv_cancel.setOnClickListener((View.OnClickListener) this);
    
     }
    

    設定寬度可以變成一個輪子反覆使用

    在設定圓角的時候一直看不到效果,是因為Dialog的背景是白色的四角方框,他承載了我們自定義的CustomDialog之後,需要把Dialog的背景變成透明才能看出圓角效果。

  • 使用CustomDialog

使用Button的點選事件喚出CustomDialog

mbtn_CustomDialog = findViewById(R.id.btn_CustomDialog);
     mbtn_CustomDialog.setOnClickListener(v -> {
         CustomDialog customDialog = new CustomDialog(RecyclerViewActivity.this, R.style.CustomDialog);
         customDialog.setTitle("提示").setMessage("確認刪除?")
                 .setConfirm("確認", new CustomDialog.IOnConfirmListener() {
                     @Override
                     public void OnConfirm(CustomDialog dialog) {
                         Toast.makeText(RecyclerViewActivity.this, "確認", Toast.LENGTH_LONG).show();
                     }
                 }).setCancel("取消", new CustomDialog.IOnCancelListener() {
             @Override
             public void OnCancel(CustomDialog dialog) {
                 Toast.makeText(RecyclerViewActivity.this, "取消", Toast.LENGTH_LONG).show();
             }
         }).show();
     });
  • CustomDialog設定圓角

我們先建立一個shape型別的xml檔案bg_custom_dialog.xml放在drawable中

宣告如下:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
 android:shape="rectangle">
 <solid android:color="@color/white"></solid>
 <corners android:radius="5dp"></corners>
</shape>

其中solid設定顏色,corners設定圓角

最後在CustomDialog的layout檔案layout_custom_dialog.xml中設定背景為bg_custom_dialog.xml即可

<LinearLayout
 ...
 android:background="@drawable/bg_custom_dialog">
 ...
</LinearLayout>

即可達到設定圓角的效果

  • 在使用LinearLayout需要注意的問題
    • 在宣告LinearLayout之後需要設定其orientation(對齊方式),可以是
      • horizontal 水平對齊
      • vertical 垂直對齊
  • PopupWindow
    • 預設用法
  • 預設用法
            mPop = new PopupWindow(view, mBtnPop.getWidth(), ViewGroup.LayoutParams.WRAP_CONTENT);
            mPop.setOutsideTouchable(true); // 設定為true之後,點選popupwindow之外的地方會使popupwindow消失
            mPop.setFocusable(true); // 設定為true之後,點選mbtnPop會使popupwindow消失,原先為點選mbtnPop會消失再出現
            mPop.showAsDropDown(mBtnPop);

可以直接new一個PopupWindow,然後接受一個view作為window的佈局,接受一個寬度和一個高度

呼叫showAsDropDown會讓PopupWindow從mbtnPop這個按鈕的下方彈出