我們自己清楚绿淋,android的原生控件實(shí)在是不堪入目,在很多時(shí)候無法滿足項(xiàng)目需求止毕,所以在項(xiàng)目進(jìn)行的過程中模蜡,我們很多時(shí)候就需要自定義控件,繼承重寫從而實(shí)現(xiàn)我們的需求扁凛。并且自定義控件將體現(xiàn)代碼的復(fù)用忍疾,分層的架構(gòu)學(xué)管理,妙用無窮令漂。本文將詳細(xì)介紹自定義Dialog的多種思路以及給出如何進(jìn)行自定義控件的指南膝昆。
文章結(jié)構(gòu)(兩種思路實(shí)現(xiàn)):1.復(fù)用率不高的丸边,而且在dialog進(jìn)行的邏輯處理較多的情況下叠必,建議使用將dialog封裝成一個(gè)類,繼承基本的Dialog類實(shí)現(xiàn)妹窖。(在這里的后面會詳細(xì)說明自定義樣式的問題喔N吵)2.復(fù)用率高,而且每個(gè)dialog都要求有固定的布局格式的話骄呼,建議使用一個(gè)BaseDialog類作為你實(shí)際實(shí)現(xiàn)dialog的父類
先上圖: 就是這種仿谷歌風(fēng)格的自定義dialog啦9部痢判没!
一、第一種思路實(shí)現(xiàn)的詳解:
首先當(dāng)然是你想要的dialog布局隅茎,這里你自己想怎么折騰就怎么折騰隨你澄峰。由于這里使用了radiobutton的多向運(yùn)用,可在此不詳細(xì)解析辟犀,欲想看明radiobutton的多向運(yùn)用請看我的另一篇博客: Android之RadioButton和RadioGroup結(jié)合Dialog的多種運(yùn)用詳解
<?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="廣播周期設(shè)定"
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="關(guān)閉"
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; //這里定義個(gè)title俏竞,一會可以看到是指向上面xml文件的控件title的,也就是我們可以通過這個(gè)進(jìn)行動(dòng)態(tài)修改title
private AdapterView.OnItemClickListener onItemClickListener; //這里定義了一個(gè)監(jiān)聽是為了實(shí)現(xiàn)內(nèi)部的監(jiān)聽接口處理堂竟,從而實(shí)現(xiàn)代碼分層管理
//可以看到兩個(gè)構(gòu)造器魂毁,想自定義樣式的就用第二個(gè)啦
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的方式引入,然后回調(diào)activity方法出嘹,setContentView席楚,實(shí)現(xiàn)自定義布局
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);
//設(shè)置dialog大小,這里是一個(gè)小贈送税稼,模塊好的控件大小設(shè)置
Window dialogWindow = getWindow();
WindowManager manager = ((Activity) context).getWindowManager();
WindowManager.LayoutParams params = dialogWindow.getAttributes(); // 獲取對話框當(dāng)前的參數(shù)值
dialogWindow.setGravity(Gravity.CENTER);//設(shè)置對話框位置
Display d = manager.getDefaultDisplay(); // 獲取屏幕寬烦秩、高度
params.width = (int) (d.getWidth() * 0.8); // 寬度設(shè)置為屏幕的0.65,根據(jù)實(shí)際情況調(diào)整
dialogWindow.setAttributes(params);
}
//監(jiān)聽接口
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()) {
}
}
};
}
調(diào)用:
RadioButtonDialog radioButtonDialog=new RadioButtonDialog(getActivity(),R.style.Dialog);
radioButtonDialog.setTitle("廣播周期設(shè)定");
radioButtonDialog.create();
radioButtonDialog.show();
就是這么簡單的調(diào)用郎仆,使其代碼的簡約闻镶,邏輯分層管理的實(shí)現(xiàn)了。此外丸升,大家注意到那個(gè)我們這里使用的是自定義樣式铆农。
在style文件里面定義以下:
<style name="Dialog" parent="android:style/Theme.Dialog">
<!-- 第一個(gè)是dialog的背景色,當(dāng)然你可以設(shè)置圖片狡耻,不攔大家 -->
<item name="android:background">@color/white</item>
<!-- 第二個(gè)就是彈出dialog后墩剖,下面的activity層的顏色啦-->
<item name="android:windowBackground">@android:color/transparent</item>
<!--這里設(shè)置為沒有標(biāo)題欄,如果這里不設(shè)置的話夷狰,你會發(fā)現(xiàn)無論布局怎么改都會出現(xiàn)多一欄白色 -->
<item name="android:windowNoTitle">true</item>
<item name="android:windowFrame">@null</item><!--邊框-->
</style>
好了第一種思路的實(shí)現(xiàn)就是這樣啦岭皂。這里補(bǔ)充一些關(guān)于自定義dialog樣式的style標(biāo)簽
<item name="android:windowIsFloating">true</item><!--是否浮現(xiàn)在activity之上-->
<item name="android:windowIsTranslucent">false</item><!--半透明-->
<item name="android:backgroundDimEnabled">false</item><!--模糊-->
二、第二種思路實(shí)現(xiàn)方式詳解:
首先是dialog的xml文件我們并不改變它
父類dialog的封裝:BaseDialog.java
public abstract class BaseDialog extends Dialog {
private Context context; //下面三個(gè)定義的跟上面講得就是一樣的啦
private String title;
private OnItemCheckListener onItemCheckListener;
protected View view; //看到這里我們定義的就清楚沼头,我們也是借用view這個(gè)父類來引入布局的
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);
//設(shè)置dialog大小
Window dialogWindow = getWindow();
WindowManager manager = ((Activity) context).getWindowManager();
WindowManager.LayoutParams params = dialogWindow.getAttributes(); // 獲取對話框當(dāng)前的參數(shù)值
dialogWindow.setGravity(Gravity.CENTER);
Display d = manager.getDefaultDisplay(); // 獲取屏幕寬爷绘、高度
params.width = (int) (d.getWidth() * 0.8); // 寬度設(shè)置為屏幕的0.65,根據(jù)實(shí)際情況調(diào)整
dialogWindow.setAttributes(params);
}
//可以看到這里定義了一個(gè)抽象方法进倍,這個(gè)將交由子類去實(shí)現(xiàn)
public abstract int getLayoutId();
//為了邏輯分層管理土至,接口的管理實(shí)現(xiàn)方式
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);
}
//回調(diào)這個(gè)方法啦
@Override
public int getLayoutId() {
return 0;
}
//也回調(diào)了父類的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);
}
}
實(shí)現(xiàn)的時(shí)候new出子類陶因,然后用getLayoutId來set上布局id,就可以完成啦4刮稀?铩解幽!
這里給出繼承父類dialog的布局格式的思路:
比如:標(biāo)題和確定鍵以及取消鍵都要求固定格式,實(shí)現(xiàn):
1.子類要設(shè)置布局烘苹,所以要在父類留一個(gè)設(shè)置內(nèi)容的方法躲株,就像上面父類那樣,寫一個(gè)抽象方法镣衡,然后dialog中間布局就寫一個(gè)布局并且附上id徘溢,在父類方法addView,像getLayoutId那樣捆探,然后子類回調(diào)這個(gè)方法然爆,在addView里面,set上我們自定義的dialog內(nèi)容布局就可以實(shí)現(xiàn)啦J蛲肌T瘛!
好了助被,這個(gè)就是實(shí)現(xiàn)自定義dialog的兩種思路剖张,以及如何進(jìn)行自己的自定義控件的思路詳解啦!?贰搔弄!代碼里面都有詳細(xì)解析,就此結(jié)束啦7峄顾犹!
歡迎在下方指出錯(cuò)誤,共同學(xué)習(xí)褒墨!
轉(zhuǎn)載請表明【JackFrost的博客】
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者