Androd自定義對話框Dialog視圖及參數(shù)傳遞的實現(xiàn)方法
今天給大家講講有關自定義對話框的相關內容,前面兩篇都在在利用系統(tǒng)提供的函數(shù)來實現(xiàn)對話框,但局限性太大,當我們想自己定義視圖的時候,就不能利用系統(tǒng)函數(shù)了,就需要我們這里的自定義對話框了,有關自定義對話框的東東,以前有寫過一篇《android之Dialog相關》,寫的不好,今天給大家重新寫一篇
一、雛形構建
先給大家看下這小節(jié)的效果圖:
自定義一個對話框,內容是四個ImageView橫排;

1、Dialog布局
根據(jù)上圖的對話框樣式,我們看一下Dialog的布局定義(custom_dialog.xml)
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/log_in_layout" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:layout_width="match_parent" android:layout_height="100dip" android:src="@drawable/animal1" android:clickable="true" android:layout_weight="1"/> <ImageView android:layout_width="match_parent" android:layout_height="100dip" android:src="@drawable/animal2" android:clickable="true" android:layout_weight="1"/> <ImageView android:layout_width="match_parent" android:layout_height="100dip" android:src="@drawable/animal3" android:clickable="true" android:layout_weight="1"/> <ImageView android:layout_width="match_parent" android:layout_height="100dip" android:src="@drawable/animal4" android:clickable="true" android:layout_weight="1"/> </LinearLayout>
2、從Dialog派生對話框類
有關構造函數(shù):
有三種構造函數(shù),現(xiàn)在我這里使用重寫了兩個,這里只需要使用第一個,即傳進去context即可;
有關OnCreate()
在OnCreate()時,利用LayoutInflater獲取我們對話框的View,然后利用SetContentView指定為我們CustomDialog類的布局。
public class CustomDialog extends Dialog {
Context mContext;
public CustomDialog (Context context){
super(context);
mContext = context;
}
public CustomDialog(Context context, int theme) {
super(context, theme);
mContext = context;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.custom_dialog, null);
this.setContentView(layout);
}
}
3、主函數(shù)(MainActivity)
在MainActivity中,我們寫一個Button,當用戶點擊的時候彈出我們自定義的對話框實例
MainActivity的布局:(activity_main.xml)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/btn_pop_dialog" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="彈出對話框"/> </RelativeLayout>
代碼中的處理:(MainActivity.java)
在點擊Btn的時候,創(chuàng)建CustomDialog類的實例,并顯示
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = (Button)findViewById(R.id.btn_pop_dialog);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
CustomDialog dialog = new CustomDialog(MainActivity.this);
dialog.show();
}
});
}
}
這部分源碼在文章最底部給出;
二、定義對話框樣式
這里再回頭看看上面彈出的對話框:

在布局中,我們只定義了一個水平布局,里面放了四個ImageView,即那四個小動物,那上面那一坨是哪來的呢(我用紅筆圈出來的那塊)?能不能去掉?這節(jié),我們就說說有關樣式的問題。
第一個問題,只所有上面那一坨,是因為我們沒有指定對話框樣式,系統(tǒng)會使用默認樣式,那一坨就是標題欄。
要去掉的話,我們就需要自定義樣式。
1、自定義樣式
我們的樣式是寫在res/values文件夾下的style.xml文件中的,如圖,如果沒有style.xml,自已新建一個,位置如圖:

這里定義的樣式代碼是這樣的:
<style name="dialog" parent="android:Theme.Dialog"> <item name="android:windowFrame">@null</item> <item name="android:windowIsFloating">true</item> <item name="android:windowContentOverlay">@null</item> <item name="android:windowNoTitle">true</item> </style>
先對這幾個參數(shù)解釋一下:
Android:windowFrame:界面對應的前景圖片;
android:windowIsFloating:表示浮在屏幕上的,如果在這里使用了,整個layout就會在 屏幕中心,相當于浮在屏幕上,所以這個只適用于dialog
android:windowContentOverlay:表示標題欄的陰影部分的樣式,使用圖片或者顏色
android:windowNoTitle:標題欄是否隱藏,這就是我們上面顯示的標題欄
有關樣式的內容很多很雜,這里有篇文章大家可以參考下《Andriod中Style/Theme原理以及Activity界面文件選取過程淺析》,有機會給大家總結一下有關樣式和主題的內容,到時再細講,這里不是本篇的重點,就不再細講了。
2、使用樣式
方法一:
這里有兩種方法來使用樣式,主要還是利用構造函數(shù),還記得我們上面說過,對話框的兩個構造函數(shù):
public class CustomDialog extends Dialog {
Context mContext;
public CustomDialog(Context context) {
super(context);
mContext = context;
}
public CustomDialog(Context context, int theme) {
super(context, theme);
mContext = context;
}
…………
}
看第二個就是我們的Theme樣式,所以第一種使用樣式的方法是在構造時直接將樣式傳進來,如果這樣使用,那我們在構造對話框時應該是這樣的“:

public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = (Button)findViewById(R.id.btn_pop_dialog);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
CustomDialog dialog = new CustomDialog(MainActivity.this,R.style.dialog);
dialog.show();
}
});
}
}
即在新建CustomDialog實例時,第二個參數(shù)傳進來我們上面定義的樣式。
方法二:
第二種方法,就是我們在構造時,不讓別人傳樣式,只讓傳進來Context,但在內部,我們利用Super(context,theme)來指定樣式,代碼如下:
public class CustomDialog extends Dialog {
Context mContext;
public CustomDialog(Context context) {
super(context,R.style.dialog);
mContext = context;
}
…………
}
這種情況一般用在我們封裝代碼時,不讓其它人在外部改變我們的樣式時使用的。
無論使用哪種方法,我們就已經(jīng)指定我我們的對話框樣式,現(xiàn)在的效果是這樣的:
看到了沒,上面的標題欄沒了,下面再看看有關參數(shù)傳遞的問題
三、參數(shù)傳遞
這里涉及到兩個問題:傳進去和傳出來;
傳進去:下面有兩個按鈕,當用戶點第一個按鈕時,在對話框中顯示"From btn 1",如果用戶點擊第二個按鈕,在對話框中顯示“From btn 2”
傳出來:這四個圖片都是可以點擊的,當用戶點擊任何一個圖片,把它的ID傳出來,并設置到我們的MainActivity中;
這里為了好理解,更改了對話框的布局,將水平布局改成了垂直布局。并且在MainActiviy下面加了一個ImageView.

1、傳進去
往對話框里傳參數(shù),一般就是利用構造函數(shù)來完成的,很簡單,即在對話框的構造函數(shù)上加上我們自己想要傳的參數(shù),這里我們需要額外傳一個字符串,來表示從哪個BTN來的。
所以對話框的構造函數(shù)就變成了這樣:
public class CustomDialog extends Dialog{
private Context mContext;
private String mStr;
public CustomDialog(Context context, String str, int theme) {
super(context, theme);
mContext = context;
mStr = str;
}
…………
}
在使用的時候,也很簡單:
Button btn2 = (Button)findViewById(R.id.btn_pop_dialog_2);
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
CustomDialog dialog = new CustomDialog(MainActivity.this,"From btn 2",R.style.dialog);
dialog.show();
}
});
直接利用構造函數(shù)傳參即可
2、傳出來
利用構造函數(shù)傳參數(shù)大家都知道,但要怎么把用戶的操作信息傳出來就不是那么簡單了,這里就要利用回調來實現(xiàn)了!
回調函數(shù)的使用主要依照下面這些步驟:
在對話框中:
public class CustomDialog extends Dialog {
// 利用interface來構造一個回調函數(shù)
public interface ICustomDialogEventListener {
public void customDialogEvent(int valueYouWantToSendBackToTheActivity);
}
private ICustomDialogEventListener onCustomDialogEventListener;
// 在構造函數(shù)中,設置進去回調函數(shù)
public CustomDialog(Context context,
ICustomDialogEventListener onCustomDialogEventListener) {
super(context);
this.onCustomDialogEventListener = onCustomDialogEventListener;
}
//當你想把值傳回去的時候,調用回調函數(shù)將值設置進去
@Override
public void onCreate(Bundle savedInstanceState)
{
Button btnOk = (Button) findViewById(R.id.customDialogButton);
btnOk.setOnClickListener( new Button.OnClickListener()
{
public void onClick(View v) {
onCustomDialogEventListener.customDialogEvent(valueYouWantToSendBackToTheActivity);
dismiss();
}
});
}
}
在構造對話框時:
final CustomDialog dialog = new CustomDialog(this, new ICustomDialogEventListener() {
public void customDialogEvent(int value) {
//在這里就獲取到了從對話框傳回來的值
}
});
大致使用流程就是這樣的,下面就把我們上面的效果利用回調函數(shù)實現(xiàn)出來;
首先在對話框中新建一個回調函數(shù)(接口),并且在對話框的構造方法中把回調函數(shù)傳進來:
public class CustomDialog extends Dialog implements View.OnClickListener {
//增加一個回調函數(shù),用以從外部接收返回值
public interface ICustomDialogEventListener {
public void customDialogEvent(int id);
}
private ICustomDialogEventListener mCustomDialogEventListener;
private Context mContext;
private String mStr;
//把回調函數(shù)傳進來
public CustomDialog(Context context, String str, ICustomDialogEventListener listener, int theme) {
super(context, theme);
mContext = context;
mStr = str;
mCustomDialogEventListener = listener;
}
…………
}
然后在OnCreate() 函數(shù)中設定ImageView的點擊事件,我們將CustomDialog類繼承View.OnClickListener接口,對點擊事件統(tǒng)一處理:
private void bindImageClickEvent(View layout){
ImageView img1 = (ImageView)layout.findViewById(R.id.dialog_image1);
ImageView img2 = (ImageView)layout.findViewById(R.id.dialog_image2);
ImageView img3 = (ImageView)layout.findViewById(R.id.dialog_image3);
ImageView img4 = (ImageView)layout.findViewById(R.id.dialog_image4);
img1.setOnClickListener(this);
img2.setOnClickListener(this);
img3.setOnClickListener(this);
img4.setOnClickListener(this);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.custom_dialog, null);
TextView tv = (TextView)layout.findViewById(R.id.dialog_text);
tv.setText(mStr);
bindImageClickEvent(layout);//綁定ImageView點擊事件
this.setContentView(layout);
}
在OnCreate()中,首先將傳進來的String字符串設置到對話框的TextView中;然后綁定各個ImageView的點擊事件
然后 就是在OnClick中的處理:
主要是根據(jù)用戶當前點擊的ImageView的ID,把這個ImageView所用的圖片的DrawableID返回給MainActivity,代碼如下:
public void onClick(View view) {
int id = view.getId();
int drawableID = -1;
switch (id){
case R.id.dialog_image1:
drawableID = R.drawable.animal1;
break;
case R.id.dialog_image2:
drawableID = R.drawable.animal2;
break;
case R.id.dialog_image3:
drawableID = R.drawable.animal3;
break;
case R.id.dialog_image4:
drawableID = R.drawable.animal4;
break;
}
if (drawableID != -1) {
mCustomDialogEventListener.customDialogEvent(drawableID);
}
dismiss();
}
這樣就把對話框的構造過程講完了,完整的對話框代碼是這樣的:
public class CustomDialog extends Dialog implements View.OnClickListener{
//增加一個回調函數(shù),用以從外部接收返回值
public interface ICustomDialogEventListener {
public void customDialogEvent(int id);
}
private ICustomDialogEventListener mCustomDialogEventListener;
private Context mContext;
private String mStr;
public CustomDialog(Context context) {
super(context);
mContext = context;
}
public CustomDialog(Context context, String str,ICustomDialogEventListener listener,int theme) {
super(context, theme);
mContext = context;
mStr = str;
mCustomDialogEventListener = listener;
}
private void bindImageClickEvent(View layout){
ImageView img1 = (ImageView)layout.findViewById(R.id.dialog_image1);
ImageView img2 = (ImageView)layout.findViewById(R.id.dialog_image2);
ImageView img3 = (ImageView)layout.findViewById(R.id.dialog_image3);
ImageView img4 = (ImageView)layout.findViewById(R.id.dialog_image4);
img1.setOnClickListener(this);
img2.setOnClickListener(this);
img3.setOnClickListener(this);
img4.setOnClickListener(this);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.custom_dialog, null);
TextView tv = (TextView)layout.findViewById(R.id.dialog_text);
tv.setText(mStr);
bindImageClickEvent(layout);
this.setContentView(layout);
}
@Override
public void onClick(View view) {
int id = view.getId();
int drawableID = -1;
switch (id){
case R.id.dialog_image1:
drawableID = R.drawable.animal1;
break;
case R.id.dialog_image2:
drawableID = R.drawable.animal2;
break;
case R.id.dialog_image3:
drawableID = R.drawable.animal3;
break;
case R.id.dialog_image4:
drawableID = R.drawable.animal4;
break;
}
if (drawableID != -1) {
mCustomDialogEventListener.customDialogEvent(drawableID);
}
dismiss();
}
}
下面就是構造對話框的過程了:
在MainAcitivity中,當點擊一個按鈕時,new一個ICustomDialogEventListener實例來接收傳過來的值;
Button btn = (Button)findViewById(R.id.btn_pop_dialog_1);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
CustomDialog dialog = new CustomDialog(MainActivity.this,"From btn 1",new CustomDialog.ICustomDialogEventListener() {
@Override
public void customDialogEvent(int id) {
ImageView imageView = (ImageView)findViewById(R.id.main_image);
imageView.setImageDrawable(getResources().getDrawable(id));
}
},R.style.dialog);
dialog.show();
}
});
在我們收到傳過來的DrawableID時,把它設置gc主頁面ImageVIew里顯示出來,這就完成了我們上面的功能。
好了,本文就到這里了,有關對話框的東東基本上都講完了,一般還是我們自定義對話框的時間比較多,所以這里講的啰嗦了一點;
相關文章
Android從0到完整項目(1)使用Android studio 創(chuàng)建項目詳解
本篇文章主要介紹了Android從0到完整項目(1)使用Android studio 創(chuàng)建項目詳解,具有一定的參考價值,有興趣的可以了解一下2017-07-07
InputFilter實現(xiàn)EditText文本輸入過濾器實例代碼解析
EditText是Android的文本輸入框控件。這篇文章給大家介紹 InputFilter實現(xiàn)EditText文本輸入過濾器實例代碼解析,需要的朋友一起看看吧2016-11-11
Android studio 生成帶Kotlin文檔的實現(xiàn)方式
這篇文章主要介紹了Android studio 生成帶Kotlin文檔的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03
Android Studio打包APK文件具體實現(xiàn)步驟解析
這篇文章主要介紹了Android Studio打包APK文件具體實現(xiàn)步驟解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-11-11

