Android-自定義Dialog和其樣式以及自定義控件思路詳解

我們自己清楚绿淋,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)系作者
  • 序言:七十年代末炫刷,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子郁妈,更是在濱河造成了極大的恐慌浑玛,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件噩咪,死亡現(xiàn)場離奇詭異顾彰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)胃碾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門涨享,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人书在,你說我怎么就攤上這事灰伟〔鹩郑” “怎么了儒旬?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵栏账,是天一觀的道長。 經(jīng)常有香客問我栈源,道長挡爵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任甚垦,我火速辦了婚禮茶鹃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘艰亮。我一直安慰自己闭翩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布迄埃。 她就那樣靜靜地躺著疗韵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪侄非。 梳的紋絲不亂的頭發(fā)上蕉汪,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機(jī)與錄音逞怨,去河邊找鬼者疤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛叠赦,可吹牛的內(nèi)容都是我干的驹马。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼除秀,長吁一口氣:“原來是場噩夢啊……” “哼窥翩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起鳞仙,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤寇蚊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后棍好,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仗岸,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年借笙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扒怖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,711評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡业稼,死狀恐怖盗痒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤俯邓,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布骡楼,位于F島的核電站,受9級特大地震影響稽鞭,放射性物質(zhì)發(fā)生泄漏鸟整。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一朦蕴、第九天 我趴在偏房一處隱蔽的房頂上張望篮条。 院中可真熱鬧,春花似錦吩抓、人聲如沸涉茧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽降瞳。三九已至,卻和暖如春蚓胸,著一層夾襖步出監(jiān)牢的瞬間子巾,已是汗流浹背科贬。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鸿捧。 一個(gè)月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓赐稽,卻偏偏與公主長得像瞧哟,于是被迫代替她去往敵國和親并闲。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評論 2 353

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,077評論 25 707
  • ¥開啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個(gè)線程叹哭,因...
    小菜c閱讀 6,401評論 0 17
  • 遙想想我的高中時(shí)代忍宋,不得不提起的一個(gè)人,他單名一個(gè)錕字风罩。 看《大魚海棠》時(shí)糠排,開篇第一句“北冥有魚,其名為鯤超升。鯤之大...
    窗外陽光閱讀 825評論 17 23
  • /小雨文圖 月亮淺淺還在天上 大地之上已是鳥鳴蟲唱 輕嗅一朵花的香 一縷清風(fēng)蕩漾 萬物竟綠入宦,滿目蒼翠 喜歡這樣的生...
    小雨飄飄閱讀 646評論 13 17
  • 也許大家覺得被分手很丟人,可是為啥我不會呢室琢,大概是因?yàn)槲覑鄣脹]那么深吧乾闰。我想了很久,心里也在糾結(jié)要不要說出來盈滴,但是...
    嘆嘆嘆息閱讀 254評論 0 1