Android 個(gè)性化 之 百變Dialog

前言

關(guān)于Dialog的使用可謂是相當(dāng)?shù)膹V泛揽涮,可以用來做各種處理,其中也衍生了許多種的處理方式饿肺,有好有壞蒋困,自己有必要加以拿捏,熟練了以后敬辣,便可謂是招之即來雪标,揮之即去零院。
  Dialog搭配一些個(gè)性化風(fēng)格與簡單動(dòng)畫會(huì)有一些神奇效果(Pics from Baidu_Pics):

dialog1.gif

dialog2.gif

  實(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_bottom.png

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);       // 單選條目      
single_item.png
    .setMultiChoiceItems(new String[] {"A", "B", "C", "D"}, 0, this);        // 多選條目
multi_item.png

  此外值得一說的是般甲,若是繼承了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)大之處,由此寫來給大家分享一下小小的心得~

最后再來看一張很好看的效果~


dialog_sweet.gif
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末曼氛,一起剝皮案震驚了整個(gè)濱河市豁辉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌舀患,老刑警劉巖徽级,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異聊浅,居然都是意外死亡餐抢,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進(jìn)店門低匙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來旷痕,“玉大人,你說我怎么就攤上這事努咐】噍铮” “怎么了?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵渗稍,是天一觀的道長佩迟。 經(jīng)常有香客問我,道長竿屹,這世上最難降的妖魔是什么报强? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮拱燃,結(jié)果婚禮上秉溉,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好召嘶,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布父晶。 她就那樣靜靜地躺著,像睡著了一般弄跌。 火紅的嫁衣襯著肌膚如雪甲喝。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天铛只,我揣著相機(jī)與錄音埠胖,去河邊找鬼。 笑死淳玩,一個(gè)胖子當(dāng)著我的面吹牛直撤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蜕着,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼谋竖,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了侮东?” 一聲冷哼從身側(cè)響起圈盔,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤豹芯,失蹤者是張志新(化名)和其女友劉穎悄雅,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體铁蹈,經(jīng)...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宽闲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了握牧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片容诬。...
    茶點(diǎn)故事閱讀 40,444評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖沿腰,靈堂內(nèi)的尸體忽然破棺而出览徒,到底是詐尸還是另有隱情,我是刑警寧澤颂龙,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布习蓬,位于F島的核電站,受9級特大地震影響措嵌,放射性物質(zhì)發(fā)生泄漏躲叼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一企巢、第九天 我趴在偏房一處隱蔽的房頂上張望枫慷。 院中可真熱鬧,春花似錦、人聲如沸或听。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽誉裆。三九已至再姑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間找御,已是汗流浹背元镀。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留霎桅,地道東北人栖疑。 一個(gè)月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像滔驶,于是被迫代替她去往敵國和親遇革。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評論 2 359

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,277評論 25 707
  • AlertDialog是經(jīng)常使用控件揭糕,今天我來分析一下源碼萝快。 android新手經(jīng)常會(huì)用遇到幾個(gè)問題? 窗體溢出的...
    一航j(luò)ason閱讀 8,466評論 2 1
  • ¥開啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個(gè)線程著角,因...
    小菜c閱讀 6,444評論 0 17
  • footer定位底部起初我的打算是用絕對定位吏口,脫離文本流奄容,參照瀏覽器左上角定位,設(shè)置TRBL作為原點(diǎn)此時(shí)我的代碼如...
    DecadeHeart閱讀 8,787評論 0 0
  • Vinil內(nèi)心閱讀 322評論 0 1