1. 程式人生 > >Android 自定義AlertDialog

Android 自定義AlertDialog

這幾天看了一些關於Android UI的文件,看到這個控制元件的時候感覺,怎麼會有這麼醜,這麼難用的元件,不就是一個Alert嗎?好在這個元件給我們提供了一個可以將這個元件蓋頭換面的Api,便是setView,那就以重寫這個元件為核心對AlertDialog進行重寫吧,這裡我們實驗一種最常用的使用場景,先把實現效果貼圖吧

仿照IPhone做的效果,喬幫主的產品確實簡潔美觀

首先我們先來定義一下介面中的幾個引數

// 控制元件
private TextView tv_alertdialog_message_title, tv_alertdialog_message_message;
private
Button btnPositive, btnNegative; // 傳遞引數 private String title, message; private String positiveText = "確定", negativeText = "取消";

說白了就是四個元件,接下來是繫結的事件了

// 定義確定、取消事件
public interface AlertDialogMessageListener {
    void positiveClick();
    void negativeClick();
}
// 定義一個介面物件,供呼叫者例項化
private AlertDialogMessageListener alertListener;

public
AlertDialogMessageListener getAlertListener() { return alertListener; }

接下來我們繪製一下我們自定義的介面

public void setAlertView() {
    // 佈局
    View view = (LinearLayout) LayoutInflater.from(getContext()).inflate(R.layout.alertdialog_message, null);
    // 標題
    tv_alertdialog_message_title = view.findViewById
(R.id.tv_alertdialog_message_title); tv_alertdialog_message_title.setText(title); // 資訊 tv_alertdialog_message_message = view.findViewById(R.id.tv_alertdialog_message_message); tv_alertdialog_message_message.setText(message); // Positive 按鈕 btnPositive = view.findViewById(R.id.bt_alertdialog_message_positive); btnPositive.setText(positiveText); btnPositive.setOnClickListener(this); // Negative 按鈕 btnNegative = view.findViewById(R.id.bt_alertdialog_message_negative); btnNegative.setText(negativeText); btnNegative.setOnClickListener(this); // 透明背景 Window window = getWindow(); window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); setView(view); }

細心的同學發現,我在最後直接呼叫了setView()

核心程式碼已經完成接一下我們繼續優化,正如我們大家知道的那樣,除了setView(),我們還需要按照順序,依次執行 setCancelable()、setView()(必須在create之前執行)、create()、最後才能show(),那我們何不借助方法重寫將他們全部整合起來,這樣我們在呼叫的時候就簡潔很多了,如下

 @Override
 protected void onCreate(Bundle savedInstanceState) {
     // 配置自定義View(必須在onCreate之前,否則載入失敗)
     setAlertView();
     super.onCreate(savedInstanceState);
 }

@Override
public void show() {
    // 在Show方法中直接呼叫
    setCancelable(false);
    create();
    super.show();

    // 設定 AlertDialog的 寬高和位置
    Window dialogWindow = getWindow();
    WindowManager.LayoutParams layoutParams = dialogWindow.getAttributes();
    dialogWindow.setGravity(Gravity.CENTER);
    layoutParams.width = (int) (new Metrics(getContext()).screenWidth() * 0.75);
    // 當Window的Attributes改變時系統會呼叫此函式,可以直接呼叫以應用上面對視窗引數的更改,也可以用setAttributes
    dialogWindow.setAttributes(layoutParams);
}

@Override
public void onClick(View view) {
    switch (view.getId()) {
        case R.id.bt_alertdialog_message_positive:
            if (alertListener != null) {
                getAlertListener().positiveClick();
            }
            dismiss();
            break;
        case R.id.bt_alertdialog_message_negative:
            if (alertListener != null) {
                getAlertListener().negativeClick();
            }
            dismiss();
            break;
        default:
            break;
    }
}

這樣封裝之後我們是這樣用的

//  alertDialogMessage = new AlertDialogMessage(this, "這是Component 元件", "名字為:AlertDialogMessage");
alertDialogMessage = new AlertDialogMessage(this, "這是Component 元件", "名字為:AlertDialogMessage", "走了哦", "留下吧");
alertDialogMessage.setAlertListener(this);
alertDialogMessage.show();

是不是很簡潔

對了,把遇到的問題給大家同步一下,遇到的話有個參考

1、設定圓角之後,四個角是白色填充色,解決方案如下:

// 透明背景
getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

2、無法改變彈出框的寬高,解決方案如下:

// 設定 AlertDialog的 寬高和位置
Window dialogWindow = getWindow();
WindowManager.LayoutParams layoutParams = dialogWindow.getAttributes();
dialogWindow.setGravity(Gravity.CENTER);
layoutParams.width = (int) (new Metrics(getContext()).screenWidth() * 0.75);
// 當Window的Attributes改變時系統會呼叫此函式,可以直接呼叫以應用上面對視窗引數的更改,也可以用setAttributes
dialogWindow.setAttributes(layoutParams);

避免大家對有些地方產生誤解,我把這個元件的封裝程式碼全部貼出來吧

package com.mengft.mengft_ui.Compenent;

import android.app.AlertDialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.mengft.mengft_ui.R;
import com.mengft.mengft_ui.Utils.Metrics;

/**
 * Created by mengft on 2018/6/8.
 */

public class AlertDialogMessage extends AlertDialog implements View.OnClickListener {

    // 控制元件
    private TextView tv_alertdialog_message_title, tv_alertdialog_message_message;
    private Button btnPositive, btnNegative;
    //  傳遞引數
    private String title, message;
    private String positiveText = "確定", negativeText = "取消";
    // 定義確定、取消事件
    public interface AlertDialogMessageListener {
        void positiveClick();
        void negativeClick();
    }
    // 定義一個介面物件,供呼叫者例項化
    private AlertDialogMessageListener alertListener;

    public AlertDialogMessageListener getAlertListener() {
        return alertListener;
    }

    public void setAlertListener(AlertDialogMessageListener alertListener) {
        this.alertListener = alertListener;
    }

    // 傳遞Header引數
    public AlertDialogMessage(Context context, String title, String message) {
        super(context);
        this.title = title;
        this.message = message;
    }

    // 傳遞Header、Button引數
    public AlertDialogMessage(Context context, String title, String message, String positiveText, String negativeText) {
        super(context);
        this.title = title;
        this.message = message;
        this.positiveText = positiveText;
        this.negativeText = negativeText;
    }

    /**
     * 配置自定義 View
     */
    public void setAlertView() {
        // 佈局
        View view = (LinearLayout) LayoutInflater.from(getContext()).inflate(R.layout.alertdialog_message, null);
        // 標題
        tv_alertdialog_message_title = view.findViewById(R.id.tv_alertdialog_message_title);
        tv_alertdialog_message_title.setText(title);
        // 資訊
        tv_alertdialog_message_message = view.findViewById(R.id.tv_alertdialog_message_message);
        tv_alertdialog_message_message.setText(message);
        // Positive 按鈕
        btnPositive = view.findViewById(R.id.bt_alertdialog_message_positive);
        btnPositive.setText(positiveText);
        btnPositive.setOnClickListener(this);
        // Negative 按鈕
        btnNegative = view.findViewById(R.id.bt_alertdialog_message_negative);
        btnNegative.setText(negativeText);
        btnNegative.setOnClickListener(this);
        // 透明背景
        getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        setView(view);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // 配置自定義View(必須在onCreate之前,否則載入失敗)
        setAlertView();
        super.onCreate(savedInstanceState);
    }

    @Override
    public void show() {
        // 在Show方法中直接呼叫
        setCancelable(false);
        create();
        super.show();

        // 設定 AlertDialog的 寬高和位置
        Window dialogWindow = getWindow();
        WindowManager.LayoutParams layoutParams = dialogWindow.getAttributes();
        dialogWindow.setGravity(Gravity.CENTER);
        layoutParams.width = (int) (new Metrics(getContext()).screenWidth() * 0.75);
        // 當Window的Attributes改變時系統會呼叫此函式,可以直接呼叫以應用上面對視窗引數的更改,也可以用setAttributes
        dialogWindow.setAttributes(layoutParams);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.bt_alertdialog_message_positive:
                if (alertListener != null) {
                    getAlertListener().positiveClick();
                }
                dismiss();
                break;
            case R.id.bt_alertdialog_message_negative:
                if (alertListener != null) {
                    getAlertListener().negativeClick();
                }
                dismiss();
                break;
            default:
                break;
        }
    }
}