Androd自定義對(duì)話框Dialog視圖及參數(shù)傳遞的實(shí)現(xiàn)方法
今天給大家講講有關(guān)自定義對(duì)話框的相關(guān)內(nèi)容,前面兩篇都在在利用系統(tǒng)提供的函數(shù)來實(shí)現(xiàn)對(duì)話框,但局限性太大,當(dāng)我們想自己定義視圖的時(shí)候,就不能利用系統(tǒng)函數(shù)了,就需要我們這里的自定義對(duì)話框了,有關(guān)自定義對(duì)話框的東東,以前有寫過一篇《android之Dialog相關(guān)》,寫的不好,今天給大家重新寫一篇
一、雛形構(gòu)建
先給大家看下這小節(jié)的效果圖:
自定義一個(gè)對(duì)話框,內(nèi)容是四個(gè)ImageView橫排;
1、Dialog布局
根據(jù)上圖的對(duì)話框樣式,我們看一下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派生對(duì)話框類
有關(guān)構(gòu)造函數(shù):
有三種構(gòu)造函數(shù),現(xiàn)在我這里使用重寫了兩個(gè),這里只需要使用第一個(gè),即傳進(jìn)去context即可;
有關(guān)OnCreate()
在OnCreate()時(shí),利用LayoutInflater獲取我們對(duì)話框的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中,我們寫一個(gè)Button,當(dāng)用戶點(diǎn)擊的時(shí)候彈出我們自定義的對(duì)話框?qū)嵗?br />
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="彈出對(duì)話框"/> </RelativeLayout>
代碼中的處理:(MainActivity.java)
在點(diǎn)擊Btn的時(shí)候,創(chuàng)建CustomDialog類的實(shí)例,并顯示
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(); } }); } }
這部分源碼在文章最底部給出;
二、定義對(duì)話框樣式
這里再回頭看看上面彈出的對(duì)話框:
在布局中,我們只定義了一個(gè)水平布局,里面放了四個(gè)ImageView,即那四個(gè)小動(dòng)物,那上面那一坨是哪來的呢(我用紅筆圈出來的那塊)?能不能去掉?這節(jié),我們就說說有關(guān)樣式的問題。
第一個(gè)問題,只所有上面那一坨,是因?yàn)槲覀儧]有指定對(duì)話框樣式,系統(tǒng)會(huì)使用默認(rèn)樣式,那一坨就是標(biāo)題欄。
要去掉的話,我們就需要自定義樣式。
1、自定義樣式
我們的樣式是寫在res/values文件夾下的style.xml文件中的,如圖,如果沒有style.xml,自已新建一個(gè),位置如圖:
這里定義的樣式代碼是這樣的:
<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>
先對(duì)這幾個(gè)參數(shù)解釋一下:
Android:windowFrame:界面對(duì)應(yīng)的前景圖片;
android:windowIsFloating:表示浮在屏幕上的,如果在這里使用了,整個(gè)layout就會(huì)在 屏幕中心,相當(dāng)于浮在屏幕上,所以這個(gè)只適用于dialog
android:windowContentOverlay:表示標(biāo)題欄的陰影部分的樣式,使用圖片或者顏色
android:windowNoTitle:標(biāo)題欄是否隱藏,這就是我們上面顯示的標(biāo)題欄
有關(guān)樣式的內(nèi)容很多很雜,這里有篇文章大家可以參考下《Andriod中Style/Theme原理以及Activity界面文件選取過程淺析》,有機(jī)會(huì)給大家總結(jié)一下有關(guān)樣式和主題的內(nèi)容,到時(shí)再細(xì)講,這里不是本篇的重點(diǎn),就不再細(xì)講了。
2、使用樣式
方法一:
這里有兩種方法來使用樣式,主要還是利用構(gòu)造函數(shù),還記得我們上面說過,對(duì)話框的兩個(gè)構(gòu)造函數(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; } ………… }
看第二個(gè)就是我們的Theme樣式,所以第一種使用樣式的方法是在構(gòu)造時(shí)直接將樣式傳進(jìn)來,如果這樣使用,那我們?cè)跇?gòu)造對(duì)話框時(shí)應(yīng)該是這樣的“:
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í)例時(shí),第二個(gè)參數(shù)傳進(jìn)來我們上面定義的樣式。
方法二:
第二種方法,就是我們?cè)跇?gòu)造時(shí),不讓別人傳樣式,只讓傳進(jìn)來Context,但在內(nèi)部,我們利用Super(context,theme)來指定樣式,代碼如下:
public class CustomDialog extends Dialog { Context mContext; public CustomDialog(Context context) { super(context,R.style.dialog); mContext = context; } ………… }
這種情況一般用在我們封裝代碼時(shí),不讓其它人在外部改變我們的樣式時(shí)使用的。
無論使用哪種方法,我們就已經(jīng)指定我我們的對(duì)話框樣式,現(xiàn)在的效果是這樣的:
看到了沒,上面的標(biāo)題欄沒了,下面再看看有關(guān)參數(shù)傳遞的問題
三、參數(shù)傳遞
這里涉及到兩個(gè)問題:傳進(jìn)去和傳出來;
傳進(jìn)去:下面有兩個(gè)按鈕,當(dāng)用戶點(diǎn)第一個(gè)按鈕時(shí),在對(duì)話框中顯示"From btn 1",如果用戶點(diǎn)擊第二個(gè)按鈕,在對(duì)話框中顯示“From btn 2”
傳出來:這四個(gè)圖片都是可以點(diǎn)擊的,當(dāng)用戶點(diǎn)擊任何一個(gè)圖片,把它的ID傳出來,并設(shè)置到我們的MainActivity中;
這里為了好理解,更改了對(duì)話框的布局,將水平布局改成了垂直布局。并且在MainActiviy下面加了一個(gè)ImageView.
1、傳進(jìn)去
往對(duì)話框里傳參數(shù),一般就是利用構(gòu)造函數(shù)來完成的,很簡(jiǎn)單,即在對(duì)話框的構(gòu)造函數(shù)上加上我們自己想要傳的參數(shù),這里我們需要額外傳一個(gè)字符串,來表示從哪個(gè)BTN來的。
所以對(duì)話框的構(gòu)造函數(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; } ………… }
在使用的時(shí)候,也很簡(jiǎn)單:
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(); } });
直接利用構(gòu)造函數(shù)傳參即可
2、傳出來
利用構(gòu)造函數(shù)傳參數(shù)大家都知道,但要怎么把用戶的操作信息傳出來就不是那么簡(jiǎn)單了,這里就要利用回調(diào)來實(shí)現(xiàn)了!
回調(diào)函數(shù)的使用主要依照下面這些步驟:
在對(duì)話框中:
public class CustomDialog extends Dialog { // 利用interface來構(gòu)造一個(gè)回調(diào)函數(shù) public interface ICustomDialogEventListener { public void customDialogEvent(int valueYouWantToSendBackToTheActivity); } private ICustomDialogEventListener onCustomDialogEventListener; // 在構(gòu)造函數(shù)中,設(shè)置進(jìn)去回調(diào)函數(shù) public CustomDialog(Context context, ICustomDialogEventListener onCustomDialogEventListener) { super(context); this.onCustomDialogEventListener = onCustomDialogEventListener; } //當(dāng)你想把值傳回去的時(shí)候,調(diào)用回調(diào)函數(shù)將值設(shè)置進(jìn)去 @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(); } }); } }
在構(gòu)造對(duì)話框時(shí):
final CustomDialog dialog = new CustomDialog(this, new ICustomDialogEventListener() { public void customDialogEvent(int value) { //在這里就獲取到了從對(duì)話框傳回來的值 } });
大致使用流程就是這樣的,下面就把我們上面的效果利用回調(diào)函數(shù)實(shí)現(xiàn)出來;
首先在對(duì)話框中新建一個(gè)回調(diào)函數(shù)(接口),并且在對(duì)話框的構(gòu)造方法中把回調(diào)函數(shù)傳進(jìn)來:
public class CustomDialog extends Dialog implements View.OnClickListener { //增加一個(gè)回調(diào)函數(shù),用以從外部接收返回值 public interface ICustomDialogEventListener { public void customDialogEvent(int id); } private ICustomDialogEventListener mCustomDialogEventListener; private Context mContext; private String mStr; //把回調(diào)函數(shù)傳進(jìn)來 public CustomDialog(Context context, String str, ICustomDialogEventListener listener, int theme) { super(context, theme); mContext = context; mStr = str; mCustomDialogEventListener = listener; } ………… }
然后在OnCreate() 函數(shù)中設(shè)定ImageView的點(diǎn)擊事件,我們將CustomDialog類繼承View.OnClickListener接口,對(duì)點(diǎn)擊事件統(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點(diǎn)擊事件 this.setContentView(layout); }
在OnCreate()中,首先將傳進(jìn)來的String字符串設(shè)置到對(duì)話框的TextView中;然后綁定各個(gè)ImageView的點(diǎn)擊事件
然后 就是在OnClick中的處理:
主要是根據(jù)用戶當(dāng)前點(diǎn)擊的ImageView的ID,把這個(gè)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(); }
這樣就把對(duì)話框的構(gòu)造過程講完了,完整的對(duì)話框代碼是這樣的:
public class CustomDialog extends Dialog implements View.OnClickListener{ //增加一個(gè)回調(diào)函數(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(); } }
下面就是構(gòu)造對(duì)話框的過程了:
在MainAcitivity中,當(dāng)點(diǎn)擊一個(gè)按鈕時(shí),new一個(gè)ICustomDialogEventListener實(shí)例來接收傳過來的值;
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時(shí),把它設(shè)置gc主頁面ImageVIew里顯示出來,這就完成了我們上面的功能。
好了,本文就到這里了,有關(guān)對(duì)話框的東東基本上都講完了,一般還是我們自定義對(duì)話框的時(shí)間比較多,所以這里講的啰嗦了一點(diǎn);
相關(guān)文章
Android實(shí)現(xiàn)漸變色的圓弧虛線效果
最近在學(xué)習(xí)Android的paint類的時(shí)候,學(xué)習(xí)了PathEffect路徑效果和Shader渲染效果。所以就做了下面的一個(gè)效果,其中自定義的view組主要是用DashPathEffect、SweepGradient的API形成的效果。感興趣的朋友們可以參考借鑒,下面來一起看看吧。2016-10-10android LabelView實(shí)現(xiàn)標(biāo)簽云效果
這篇文章主要為大家詳細(xì)介紹了android LabelView實(shí)現(xiàn)標(biāo)簽云效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05Android通過原生APi獲取所在位置的經(jīng)緯度
本篇文章主要介紹了Android通過原生APi獲取所在位置的經(jīng)緯度,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-07-07Android快速實(shí)現(xiàn)無預(yù)覽拍照功能
這篇文章主要為大家詳細(xì)介紹了Android快速實(shí)現(xiàn)無預(yù)覽拍照功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06