我們自己清楚,android的原生控件實在是不堪入目,在很多時候無法滿足項目需求,所以在項目進行的過程中,我們很多時候就需要自定義控件,繼承重寫從而實現我們的需求。并且自定義控件將體現代碼的復用,分層的架構學管理,妙用無窮。本文將詳細介紹自定義Dialog的多種思路以及給出如何進行自定義控件的指南。
文章結構(兩種思路實現):1.復用率不高的,而且在dialog進行的邏輯處理較多的情況下,建議使用將dialog封裝成一個類,繼承基本的Dialog類實現。(在這里的后面會詳細說明自定義樣式的問題喔!)2.復用率高,而且每個dialog都要求有固定的布局格式的話,建議使用一個BaseDialog類作為你實際實現dialog的父類
先上圖:
這里寫圖片描述
就是這種仿谷歌風格的自定義dialog啦??!
這里寫圖片描述
一、第一種思路實現的詳解:
首先當然是你想要的dialog布局,這里你自己想怎么折騰就怎么折騰隨你。由于這里使用了radiobutton的多向運用,可在此不詳細解析,欲想看明radiobutton的多向運用請看我的另一篇博客: Android之RadioButton和RadioGroup結合Dialog的多種運用詳解
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="360dp"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/icon_title"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginLeft="18dp"
android:gravity="center"
android:src="@drawable/setting" />
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_marginLeft="20dp"
android:gravity="center_vertical"
android:text="廣播周期設定"
android:textSize="17sp" />
</LinearLayout>
<RadioGroup
android:id="@+id/groupBroadcast"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="18dp"
android:layout_marginTop="10dp"
android:orientation="vertical">
<RadioButton
android:id="@+id/rbtn_BroadcastClose"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:button="@null"
android:checked="true"
android:drawableLeft="@drawable/settingbroadst_checked_style"
android:drawablePadding="20dp"
android:paddingLeft="18dp"
android:text="關閉"
android:textColor="@android:color/black"
android:textSize="17sp" />
<RadioButton
android:id="@+id/rbtn_BroadcastFifteen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_weight="1"
android:button="@null"
android:drawableLeft="@drawable/settingbroadst_checked_style"
android:drawablePadding="20dp"
android:paddingLeft="18dp"
android:text="15秒"
android:textColor="@android:color/black"
android:textSize="17sp" />
<RadioButton
android:id="@+id/rbtn_BroadcastThirty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_weight="1"
android:button="@null"
android:drawableLeft="@drawable/settingbroadst_checked_style"
android:drawablePadding="20dp"
android:paddingLeft="18dp"
android:text="30秒"
android:textColor="@android:color/black"
android:textSize="17sp" />
<RadioButton
android:id="@+id/rbtn_BroadcastFourty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_weight="1"
android:button="@null"
android:drawableLeft="@drawable/settingbroadst_checked_style"
android:drawablePadding="20dp"
android:paddingLeft="18dp"
android:text="45秒"
android:textColor="@android:color/black"
android:textSize="17sp" />
<RadioButton
android:id="@+id/rbtn_BroadcastMinute"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginTop="10dp"
android:layout_weight="1"
android:button="@null"
android:drawableLeft="@drawable/settingbroadst_checked_style"
android:drawablePadding="20dp"
android:paddingLeft="18dp"
android:text="60秒"
android:textColor="@android:color/black"
android:textSize="17sp" />
</RadioGroup>
</LinearLayout>
然后就是封裝的dialog的類啦
package org.fishDroneGCS.view;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import org.fishDroneGCS.android.R;
/**
* Created by 符柱成on 2016/8/7.
*/
public class RadioButtonDialog extends Dialog {
private Context context;
private String title; //這里定義個title,一會可以看到是指向上面xml文件的控件title的,也就是我們可以通過這個進行動態修改title
private AdapterView.OnItemClickListener onItemClickListener; //這里定義了一個監聽是為了實現內部的監聽接口處理,從而實現代碼分層管理
//可以看到兩個構造器,想自定義樣式的就用第二個啦
public RadioButtonDialog(Context context) {
super(context);
this.context = context;
}
public RadioButtonDialog(Context context, int theme) {
super(context, theme);
this.context = context;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
}
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public void setOnItemClickListener(AdapterView.OnItemClickListener onItemClickListener) {
if (onItemClickListener != null)
this.onItemClickListener = onItemClickListener;
}
//控件的聲明
RadioButton rbtn_BroadcastClose;
RadioButton rbtn_BroadcastFifteen;
RadioButton rbtn_BroadcastThirty;
RadioButton rbtn_BroadcastFourty;
RadioButton rbtn_BroadcastMinute;
private void init() {
//以view的方式引入,然后回調activity方法,setContentView,實現自定義布局
View view = LayoutInflater.from(context).inflate(R.layout.dialog_broadcast, null);
setContentView(view);
//radiobutton的初始化
RadioGroup groupBroadcast = (RadioGroup) view.findViewById(R.id.groupBroadcast);
rbtn_BroadcastClose = (RadioButton) view.findViewById(R.id.rbtn_BroadcastClose);
rbtn_BroadcastFifteen = (RadioButton) view.findViewById(R.id.rbtn_BroadcastFifteen);
rbtn_BroadcastThirty = (RadioButton) view.findViewById(R.id.rbtn_BroadcastThirty);
rbtn_BroadcastFourty = (RadioButton) view.findViewById(R.id.rbtn_BroadcastFourty);
rbtn_BroadcastMinute = (RadioButton) view.findViewById(R.id.rbtn_BroadcastMinute);
groupBroadcast.setOnCheckedChangeListener(listener);
//設置dialog大小,這里是一個小贈送,模塊好的控件大小設置
Window dialogWindow = getWindow();
WindowManager manager = ((Activity) context).getWindowManager();
WindowManager.LayoutParams params = dialogWindow.getAttributes(); // 獲取對話框當前的參數值
dialogWindow.setGravity(Gravity.CENTER);//設置對話框位置
Display d = manager.getDefaultDisplay(); // 獲取屏幕寬、高度
params.width = (int) (d.getWidth() * 0.8); // 寬度設置為屏幕的0.65,根據實際情況調整
dialogWindow.setAttributes(params);
}
//監聽接口
private RadioGroup.OnCheckedChangeListener listener = new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (checkedId == rbtn_BroadcastClose.getId()) {
} else if (checkedId == rbtn_BroadcastFifteen.getId()) {
} else if (checkedId == rbtn_BroadcastThirty.getId()) {
} else if (checkedId == rbtn_BroadcastFourty.getId()) {
} else if (checkedId == rbtn_BroadcastMinute.getId()) {
}
}
};
}
調用:
RadioButtonDialog radioButtonDialog=new RadioButtonDialog(getActivity(),R.style.Dialog);
radioButtonDialog.setTitle("廣播周期設定");
radioButtonDialog.create();
radioButtonDialog.show();
就是這么簡單的調用,使其代碼的簡約,邏輯分層管理的實現了。此外,大家注意到那個我們這里使用的是自定義樣式。
在style文件里面定義以下:
<style name="Dialog" parent="android:style/Theme.Dialog">
<!-- 第一個是dialog的背景色,當然你可以設置圖片,不攔大家 -->
<item name="android:background">@color/white</item>
<!-- 第二個就是彈出dialog后,下面的activity層的顏色啦-->
<item name="android:windowBackground">@android:color/transparent</item>
<!--這里設置為沒有標題欄,如果這里不設置的話,你會發現無論布局怎么改都會出現多一欄白色 -->
<item name="android:windowNoTitle">true</item>
<item name="android:windowFrame">@null</item><!--邊框-->
</style>
好了第一種思路的實現就是這樣啦。這里補充一些關于自定義dialog樣式的style標簽
<item name="android:windowIsFloating">true</item><!--是否浮現在activity之上-->
<item name="android:windowIsTranslucent">false</item><!--半透明-->
<item name="android:backgroundDimEnabled">false</item><!--模糊-->
二、第二種思路實現方式詳解:
首先是dialog的xml文件我們并不改變它
父類dialog的封裝:BaseDialog.java
public abstract class BaseDialog extends Dialog {
private Context context; //下面三個定義的跟上面講得就是一樣的啦
private String title;
private OnItemCheckListener onItemCheckListener;
protected View view; //看到這里我們定義的就清楚,我們也是借用view這個父類來引入布局的
public BaseDialog(Context context) {
super(context);
}
public BaseDialog(Context context, int themeResId) {
super(context, themeResId);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
}
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public void setOnItemCheckListener(OnItemCheckListener onItemCheckListener) {
if (onItemCheckListener != null)
this.onItemCheckListener = onItemCheckListener;
}
protected void init() {
//以view來引入布局
View view = LayoutInflater.from(context).inflate(getLayoutId(), null);
this.view=view;
setContentView(view);
//設置dialog大小
Window dialogWindow = getWindow();
WindowManager manager = ((Activity) context).getWindowManager();
WindowManager.LayoutParams params = dialogWindow.getAttributes(); // 獲取對話框當前的參數值
dialogWindow.setGravity(Gravity.CENTER);
Display d = manager.getDefaultDisplay(); // 獲取屏幕寬、高度
params.width = (int) (d.getWidth() * 0.8); // 寬度設置為屏幕的0.65,根據實際情況調整
dialogWindow.setAttributes(params);
}
//可以看到這里定義了一個抽象方法,這個將交由子類去實現
public abstract int getLayoutId();
//為了邏輯分層管理,接口的管理實現方式
public interface OnItemCheckListener {
void onItemCheck(int checkedId);
}
}
然后就是到了我們具體的dialog子類啦。
public class RadioButtonDialog extends BaseDialog {
private Context context;
private String title;
private OnItemCheckListener onItemCheckListener;
public RadioButtonDialog(Context context) {
super(context);
this.context = context;
}
public RadioButtonDialog(Context context, int theme) {
super(context, theme);
}
//回調這個方法啦
@Override
public int getLayoutId() {
return 0;
}
//也回調了父類的init,利用getLayoutId傳入了布局的id
@Override
protected void init() {
super.init();
RadioGroup groupBroadcast = (RadioGroup) view.findViewById(R.id.groupBroadcast);
groupBroadcast.setOnCheckedChangeListener(listener);
}
private RadioGroup.OnCheckedChangeListener listener = new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
onItemCheckListener.onItemCheck(checkedId);
}
};
public interface OnItemCheckListener {
void onItemCheck(int checkedId);
}
}