Android-自定义Dialog和其样式以及自定义控件思路详解

我们自己清楚,android的原生控件实在是不堪入目,在很多时候无法满足项目需求,所以在项目进行的过程中,我们很多时候就需要自定义控件,继承重写从而实现我们的需求。并且自定义控件将体现代码的复用,分层的架构学管理,妙用无穷。本文将详细介绍自定义Dialog的多种思路以及给出如何进行自定义控件的指南。


文章结构(两种思路实现):1.复用率不高的,而且在dialog进行的逻辑处理较多的情况下,建议使用将dialog封装成一个类,继承基本的Dialog类实现。(在这里的后面会详细说明自定义样式的问题喔!)2.复用率高,而且每个dialog都要求有固定的布局格式的话,建议使用一个BaseDialog类作为你实际实现dialog的父类


先上图:
这里写图片描述
就是这种仿谷歌风格的自定义dialog啦!!


一、第一种思路实现的详解:

首先当然是你想要的dialog布局,这里你自己想怎么折腾就怎么折腾随你。由于这里使用了radiobutton的多向运用,可在此不详细解析,欲想看明radiobutton的多向运用请看我的另一篇博客: Android之RadioButton和RadioGroup结合Dialog的多种运用详解

<?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="广播周期设定"
            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="关闭"
            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;     //这里定义个title,一会可以看到是指向上面xml文件的控件title的,也就是我们可以通过这个进行动态修改title
    private AdapterView.OnItemClickListener   onItemClickListener;      //这里定义了一个监听是为了实现内部的监听接口处理,从而实现代码分层管理
//可以看到两个构造器,想自定义样式的就用第二个啦
    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的方式引入,然后回调activity方法,setContentView,实现自定义布局
        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);
        //设置dialog大小,这里是一个小赠送,模块好的控件大小设置
        Window dialogWindow = getWindow();
        WindowManager manager = ((Activity) context).getWindowManager();
        WindowManager.LayoutParams params = dialogWindow.getAttributes(); // 获取对话框当前的参数值
        dialogWindow.setGravity(Gravity.CENTER);//设置对话框位置
        Display d = manager.getDefaultDisplay(); // 获取屏幕宽、高度
        params.width = (int) (d.getWidth() * 0.8); // 宽度设置为屏幕的0.65,根据实际情况调整
        dialogWindow.setAttributes(params);

    }
    //监听接口
    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()) {

            }
        }
    };
}

调用:

  RadioButtonDialog radioButtonDialog=new RadioButtonDialog(getActivity(),R.style.Dialog);
        radioButtonDialog.setTitle("广播周期设定");
        radioButtonDialog.create();
        radioButtonDialog.show();

就是这么简单的调用,使其代码的简约,逻辑分层管理的实现了。此外,大家注意到那个我们这里使用的是自定义样式。

在style文件里面定义以下:

  <style name="Dialog" parent="android:style/Theme.Dialog">
  <!-- 第一个是dialog的背景色,当然你可以设置图片,不拦大家 -->
        <item name="android:background">@color/white</item>
        <!-- 第二个就是弹出dialog后,下面的activity层的颜色啦-->
        <item name="android:windowBackground">@android:color/transparent</item>
        <!--这里设置为没有标题栏,如果这里不设置的话,你会发现无论布局怎么改都会出现多一栏白色 -->
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowFrame">@null</item><!--边框-->
    </style>

好了第一种思路的实现就是这样啦。这里补充一些关于自定义dialog样式的style标签

<item name="android:windowIsFloating">true</item><!--是否浮现在activity之上-->
<item name="android:windowIsTranslucent">false</item><!--半透明-->
<item name="android:backgroundDimEnabled">false</item><!--模糊-->

二、第二种思路实现方式详解:

首先是dialog的xml文件我们并不改变它

父类dialog的封装:BaseDialog.java

public abstract class BaseDialog extends Dialog {

    private Context context;    //下面三个定义的跟上面讲得就是一样的啦
    private String title;   
    private OnItemCheckListener onItemCheckListener;
    protected View view;    //看到这里我们定义的就清楚,我们也是借用view这个父类来引入布局的

    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);
        //设置dialog大小
        Window dialogWindow = getWindow();
        WindowManager manager = ((Activity) context).getWindowManager();
        WindowManager.LayoutParams params = dialogWindow.getAttributes(); // 获取对话框当前的参数值
        dialogWindow.setGravity(Gravity.CENTER);
        Display d = manager.getDefaultDisplay(); // 获取屏幕宽、高度
        params.width = (int) (d.getWidth() * 0.8); // 宽度设置为屏幕的0.65,根据实际情况调整
        dialogWindow.setAttributes(params);
    }


//可以看到这里定义了一个抽象方法,这个将交由子类去实现
    public abstract int getLayoutId();
//为了逻辑分层管理,接口的管理实现方式
    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);
    }
//回调这个方法啦
    @Override
    public int getLayoutId() {
        return 0;
    }
//也回调了父类的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);
    }

}

实现的时候new出子类,然后用getLayoutId来set上布局id,就可以完成啦!!!


这里给出继承父类dialog的布局格式的思路:

比如:标题和确定键以及取消键都要求固定格式,实现:

1.子类要设置布局,所以要在父类留一个设置内容的方法,就像上面父类那样,写一个抽象方法,然后dialog中间布局就写一个布局并且附上id,在父类方法addView,像getLayoutId那样,然后子类回调这个方法,在addView里面,set上我们自定义的dialog内容布局就可以实现啦!!!

好了,这个就是实现自定义dialog的两种思路,以及如何进行自己的自定义控件的思路详解啦!!!代码里面都有详细解析,就此结束啦!!

欢迎在下方指出错误,共同学习!

转载请表明【JackFrost的博客】

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,198评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,663评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,985评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,673评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,994评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,399评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,717评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,407评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,112评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,371评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,891评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,255评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,881评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,010评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,764评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,412评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,299评论 2 260

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,544评论 25 707
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,191评论 0 17
  • 遥想想我的高中时代,不得不提起的一个人,他单名一个锟字。 看《大鱼海棠》时,开篇第一句“北冥有鱼,其名为鲲。鲲之大...
    窗外阳光阅读 783评论 17 23
  • /小雨文图 月亮浅浅还在天上 大地之上已是鸟鸣虫唱 轻嗅一朵花的香 一缕清风荡漾 万物竟绿,满目苍翠 喜欢这样的生...
    小雨飘飘阅读 629评论 13 17
  • 也许大家觉得被分手很丢人,可是为啥我不会呢,大概是因为我爱得没那么深吧。我想了很久,心里也在纠结要不要说出来,但是...
    叹叹叹息阅读 236评论 0 1