中级实训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中

image-20201123124853041

声明如下:

<?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这个按钮的下方弹出

原文地址:https://www.cnblogs.com/lwfing/p/14053968.html