前言
關(guān)于Dialog的使用可謂是相當(dāng)?shù)膹V泛揽涮,可以用來做各種處理,其中也衍生了許多種的處理方式饿肺,有好有壞蒋困,自己有必要加以拿捏,熟練了以后敬辣,便可謂是招之即來雪标,揮之即去零院。
Dialog搭配一些個(gè)性化風(fēng)格與簡單動(dòng)畫會(huì)有一些神奇效果(Pics from Baidu_Pics):
實(shí)現(xiàn)類似的展示效果并不難,接下來會(huì)在頁面的基礎(chǔ)上加入一些回調(diào)設(shè)置的說明村刨,在開始之后還是先來看下其繼承結(jié)構(gòu)吧:
java.lang.Object
? android.app.Dialog
-->implements DialogInterface, KeyEvent.Callback, View.OnCreateContextMenuListener, Window.Callback
由此可知告抄,Dialog是一個(gè)可以獨(dú)立的控件,而DialogInterface和KeyEvent.Callback也說明其是一個(gè)回調(diào)性很強(qiáng)的Object嵌牺,在諸多的Dialog實(shí)例中打洼,其子類AlertDialog是一種很好的實(shí)現(xiàn)方式,下面會(huì)具體介紹逆粹。
Dialog的初始化
Dialog和普通的View不同募疮,它有自己的生命周期。
通過onCreate( )創(chuàng)建
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_dialog);
}
可以看出和Activity的onCreate( )類似僻弹,也可以在其中加入一些init( )方法對layout文件中的子控件進(jìn)行監(jiān)聽等阿浓。下面看一下調(diào)用方式:
MyDialog myDialog = new MyDialog(this);
myDialog.setCanceledOnTouchOutside(false);
myDialog.show();
// 具體邏輯通過構(gòu)造方法創(chuàng)建
public MyDialog(Activity activity, int resLayout) {
super(activity, R.style.myDialog);
this.activity = activity;
this.resLayout = resLayout;
}
構(gòu)造方法中的參數(shù)可以根據(jù)需求來定義,一般不超過5個(gè)蹋绽,不然會(huì)影響性能芭毙,下面看一下調(diào)用方式:
MyDialog myDialog = new MyDialog(this, R.style.myDialog, R.layout.my_dialog);
myDialog.show();-
創(chuàng)建與銷毀時(shí)的細(xì)節(jié)
而這兩種創(chuàng)建方法卻有一點(diǎn)不同:onCreate( )創(chuàng)建的Dialog的邏輯處理需在show( )之后,相當(dāng)于調(diào)用了show( )之后才會(huì)真正的創(chuàng)建出來卸耘,而通過構(gòu)造方法創(chuàng)建的Dialog的show( )可以放在最后的位置稿蹲,相當(dāng)于一個(gè)整體的展示。
而一般自定義的Dialog由于個(gè)性化需求較大鹊奖,所以其style一般需要簡單定制一下:<!-- 自定義Dialog的Theme定義 --> <style name="myDialog" parent="android:Theme.Dialog"> <item name="android:windowFrame">@null</item> <item name="android:windowNoTitle">true</item> <item name="android:windowIsFloating">true</item> <item name="android:windowContentOverlay">@null</item> <item name="android:windowBackground">@android:color/transparent</item> </style>
對于Dialog的銷毀苛聘,有兩種方法:dismiss( )和cancel( ),仔細(xì)的童鞋會(huì)發(fā)現(xiàn)cancel( )其實(shí)中調(diào)用了dismiss( )的忠聚,只是加了一個(gè)對mCancelMessage的判斷设哗,看下該源碼:
public void setOnCancelListener(final OnCancelListener listener) {
if (listener != null) {
mCancelMessage = mListenersHandler.obtainMessage(CANCEL, listener);
} else {
mCancelMessage = null;
}
}
public void setCancelMessage(final Message msg) {
mCancelMessage = msg;
}
也就是說,如果調(diào)用了setOnCancelListener两蟀,這個(gè)mCancelMessage變量有作用网梢,否則dismiss( )和cancel( )等同。
此外赂毯,還可以對Dialog的透明战虏,展出方向(上下左右)等進(jìn)行設(shè)置,如下圖便是一個(gè)底部彈出的Dialog:
Dialog的回調(diào)監(jiān)聽
Keep your eyes on......重點(diǎn)來了党涕,關(guān)于Dialog最重要的除了展示效果外無非就是其回調(diào)的設(shè)置了烦感,而其回調(diào)方式有很多種,有把Dialog當(dāng)作Activity的方式來處理的膛堤,有使用DialogInterface來處理的手趣,有把Dialog當(dāng)作View的方式來處理,還有使用loop/handler的方式來處理的......總之有很多種方式肥荔,具體的邏輯與效率總有優(yōu)劣之處绿渣,請大家自己掌控~下面來一一介紹:
Dialog VS Handler
使用Handler的方式朝群,可以通過構(gòu)造函數(shù)傳遞參數(shù),然后在消息隊(duì)列中捕獲并處理中符,這種方式比較簡潔姜胖,在調(diào)用的位置加上:
myDialog.setHandler(mHandler);
在Dialog中:
private void setHandler(mHandler) {
this.mHandler = mHandler;
}
然后便是在Activity中通過handleMessage(msg)方法進(jìn)行處理,當(dāng)然可以在此進(jìn)行優(yōu)化淀散,使用靜態(tài)內(nèi)部類InnerHandler + 弱引用WeakReference的方式(附參考鏈接)右莱,將具體的回調(diào)設(shè)置在此處處理。Dialog VS DialogFragment
DialogFragment集Dialog與Fragment于一身吧凉,貌似很強(qiáng)大隧出。DialogFragment配合DialogInterface使用比較切合踏志,在調(diào)用的位置:
MyDialog myDialog = new MyDialog(this, R.style.myDialog, R.layout.my_dialog);
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
myDialog.show(fragmentTransaction, null);
而此時(shí)的MyDialog需要繼承自DialogFragment阀捅,即按Fragment的方式來初始化Dialog,在我們需要回調(diào)處理的地方:
MyActivity instance = (MyActivity) getActivity();
instance.onDialogBack();
即相當(dāng)于回調(diào)了Activity中的onDialogBack( )方法:
public void onDialogBack() {
// 具體邏輯
}-
Dialog VS setListener( )
看過我以前自定義View的童鞋一定也了解其實(shí)現(xiàn)思路针余,即在Dialog中加入一些setListener( )方法饲鄙,然后在實(shí)例化后直接該用內(nèi)部的setListener( )方法即可,兩種創(chuàng)建方式都可行圆雁,只需將myDialog對象調(diào)用MyDialog中的方法:
Dialog中:
public void setMyVisibility(boolean visibility) {
mView.setVisibility(visibility ? View.VISIBLE : View.GONE);
}Activity中: myDialog.setMyVisibility(true);
-
Example
結(jié)合了以上各個(gè)思路忍级,下面給出兩種可以拿來封裝的樣式,底部彈出的Dialog與居中彈出的Dialog:
dialog_style1.png
dialog_style2.png
AlertDialog初探
AlertDialog是一種極其個(gè)性化的Dialog伪朽,相當(dāng)于一個(gè)樣式封裝好的Dialog轴咱,便于調(diào)用,默認(rèn)的風(fēng)格便是一種最簡單的處理烈涮,當(dāng)然也可以自定義朴肺,在其初始化時(shí)使用了強(qiáng)大且神奇的Build-建造者模式。
AlertDialog的構(gòu)造方法全部是Protected的坚洽,所以不能直接通過new一個(gè)AlertDialog來創(chuàng)建出一個(gè)AlertDialog戈稿,需要用到AlertDialog.Builder中的create()方法:
Dialog alertDialog = new AlertDialog.Builder(this)
.setTitle("Title") // 標(biāo)題
.setMessage("Content") // 內(nèi)容
.setPositiveButton("OK", this) // Positive Button
.setNegativeButton("Cancel", this); // Negative Button
.setNeutralButton("Neutral", this); // Neutral Button
.setItems(new String[] {"A", "B", "C"}, this); // 條目
.setIcon(R.drawable.ic_launcher) // 圖標(biāo)
.create();
alertDialog.show();
因?yàn)槭墙ㄔ煺吣J剑陨厦孢@些Build的內(nèi)容都是Optional的讶舰,而其中若想添加監(jiān)聽鞍盗,可以這樣實(shí)現(xiàn):
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
})
針對于其中的setItem( ),也可以有這樣的擴(kuò)展跳昼,效果如下:
.setSingleChoiceItems(new String[] {"A", "B", "C", "D"}, 0, this); // 單選條目
.setMultiChoiceItems(new String[] {"A", "B", "C", "D"}, 0, this); // 多選條目
此外值得一說的是般甲,若是繼承了DialogFragment,則在使用了AlertDialog的setButton( )后鹅颊,可以重寫父類的onClick( )方法直接回調(diào)欣除,感覺很強(qiáng)大的樣子:
@Override
public void onClick(DialogInterface dialog, int which) {
switch(which) {
case AlertDialog.BUTTON_NEGATIVE:
// TODO
break;
case AlertDialog.BUTTON_NEGATIVE:
// TODO
break;
// TODO
}
}
當(dāng)然AlertDialog還有很多方法,這里就不一一介紹了挪略,其中pedant大神對其有仔細(xì)研究历帚,有興趣的可以去看看他的sweet-alert-dialog滔岳。我以前也參考過一些用例,簡單寫過一個(gè)AlertDialogDemo挽牢,大家也可以參考一下~
尾聲
關(guān)于Dialog這部分自己是一點(diǎn)一點(diǎn)踩過了許多坑谱煤,然后總結(jié)了許多種實(shí)現(xiàn)方式從而最終Get到其強(qiáng)大之處,由此寫來給大家分享一下小小的心得~
附Android手機(jī)錄視頻轉(zhuǎn)Gif格式與Video 轉(zhuǎn) Gif 實(shí)戰(zhàn)
Github地址:
https://github.com/IvorfasonGithub博客:
http://ivorfason.github.io個(gè)人網(wǎng)站:
http://www.ivorfason.site個(gè)人郵箱:(我覺得QQ郵箱很高大上禽拔,You can you upA趵搿)
justforyouymr@qq.com雜談一下
關(guān)于Dialog的實(shí)現(xiàn)與自定義控件、自定義View其實(shí)也有一定的相似之處睹栖,當(dāng)然更多的是Dialog的整體性較高硫惕,回調(diào)性與多元性可以很復(fù)雜,具體邏輯需要自己結(jié)合項(xiàng)目實(shí)際需求加以調(diào)控野来,這樣的Personality便會(huì)很有意義恼除。后期會(huì)不定期更新自己的學(xué)習(xí)心得,歡迎大家查漏補(bǔ)缺......
最后再來看一張很好看的效果~