Builder设计模式构建整个应用的头部(NavigationBar)

开发中基本上每个APP都会有自己的头部,如何去写这个头部呢?一部分人会在xml布局中直接写,一部分人会调用系统的ToolBar自定义布局,这两种方式都可以去实现,但是有个问题,如果产品频繁让你改这个头部你会不会崩溃呢?
A : “我自己写的,我都清楚哪个控件是什么,有什么用,改一下也不费事”
B : "慢慢捋还是可以改的";
我想说 既然每个应用都能用到这个头部 为什么不能进一步封装一下呢?一句代码搞定的事没有必要写很多行。
这一期我们来看一下如何利用Builder设计模式构建整个应用的NavigationBar,再也不必在activity中写任何布局,而且一行解决头部的问题。

  • 首选看一下我们要写的NavigationBar的结构图


    NavationBar结构图.png

通过图可以知道,首先先写个接口用来规范头部,然后写个abstract基类,再写一个DefaultNavigationBar去实现这个抽象类,特殊情况特殊对待吧。
1.定义头部规范接口

/**
 * 导航栏规范
 */
public interface INavigation {
    //绑定头部ID
    public int bindLayoutId();
    //绑定头部参数
    public void applyView();
}

2.创建一个基类AbsNavigationBar
在创建前先稍微讲一下builder设计模式的构造 看图。


build模式结构图.png
/**
 * Created by LiMing on 2018/4/24.
 * QQ:1002464056
 * Email: 1002464056@qq.com
 * Version:1.0
 * 基类(所有的在此基础上写)
 */

public abstract class AbsNavigationBar<P extends AbsNavigationBar.Build.AbsNavigationBarParmas>implements INavigation {

    private P mParmas;
    private View mNavigationView;

    public AbsNavigationBar(P parmas){
        this.mParmas=parmas;
        creatAndBind();
    }

    public P getmParmas() {
        return mParmas;
    }

   
    //创建和绑定视图
    private void creatAndBind() {
        if (mParmas.mParent==null) {
            //获取根布局
            ViewGroup viewGroup = ((Activity) mParmas.mContext).findViewById(android.R.id.content);
            // 将根布局中第一个视图作为父容器(linearLayout)
            mParmas.mParent= (ViewGroup) viewGroup.getChildAt(0);
        }
        if (mParmas.mParent==null) {
            return;
        }
        //创建头部视图
        mNavigationView= LayoutInflater.from(mParmas.mContext).inflate(R.layout.title_bar,mParmas.mParent,false);

        //将头部视图添加到父容器中
        mParmas.mParent.addView(mNavigationView,0);
        //调用设置参数的方法
       applyView();
    }


    public abstract static class Build{
        public Build (Context context,ViewGroup parent){}

        // 创建一个 AbsNavigationBar
        public abstract AbsNavigationBar builder();

        public static class AbsNavigationBarParmas{
            public Context mContext;
            public ViewGroup mParent;
            public AbsNavigationBarParmas(Context context,ViewGroup parent){
                this.mContext=context;
                this.mParent=parent;
            }
        }
    }

}

3.实现类 DefaultNavigationBar 实现基类,然后在此基础上添加设置,如修改文字,设置监听之类的


/**
 * Created by LiMing on 2018/4/24.
 * QQ:1002464056
 * Email: 1002464056@qq.com
 * Version:1.0
 */

public class DefaultNavigationBar extends AbsNavigationBar<DefaultNavigationBar.Build.DefaultNavigationBarParmas> {



    public DefaultNavigationBar(DefaultNavigationBar.Build.DefaultNavigationBarParmas parmas) {
        super(parmas);
    }

    @Override
    public int bindLayoutId() {
        return R.layout.title_bar;
    }

    @Override
    public void applyView() {
        //实现设置的参数
        //设置标题
        setText(R.id.title,getmParmas().mTitle);
        //设置左边文字
        setText(R.id.left_text,getmParmas().leftText);
        // 设置左边图片的点击事件
        setOnClickListener(R.id.back,getmParmas().leftClickListener);
    }




    public static class Build extends AbsNavigationBar.Build{

        DefaultNavigationBarParmas p;
        public Build(Context context, ViewGroup parent) {
            super(context, parent);
            //创建DefaultNavigationBarParma 对象
            p=new DefaultNavigationBarParmas(context,parent);
        }
        public Build(Context context) {
            super(context, null);
            p=new DefaultNavigationBarParmas(context,null);
        }

        @Override
        public DefaultNavigationBar builder() {

            DefaultNavigationBar defaultNavigationBar=new DefaultNavigationBar(p);
            return defaultNavigationBar;
        }
        // 1.设置参数

        /**
         * 设置title
         * @param title
         * @return
         */
        public DefaultNavigationBar.Build setTitle(String title){
            p.mTitle=title;
            return this;
        }

        /**
         * 设置左边的文字
         * @param leftText
         * @return
         */
        public DefaultNavigationBar.Build setLeftText(String leftText){
            p.leftText=leftText;
            return this;
        }

        /**
         * 设置左边图片监听
         * @param clickListener
         * @return
         */
        public DefaultNavigationBar.Build setLeftImageClickListener(View.OnClickListener clickListener){
            p.leftClickListener=clickListener;
            return this;
        }

        public class DefaultNavigationBarParmas extends AbsNavigationBarParmas{

            //2.参数存放的位置
            public String mTitle;
            public String leftText;
            public View.OnClickListener leftClickListener;
            public DefaultNavigationBarParmas(Context context, ViewGroup parent) {
                super(context, parent);
            }
        }

    }
}

通用的80%的功能在此基本可以实现,我只是写了几个方法,有需要的要继续完善,剩下的特殊的20%的功能需要自己去实现了。
具体怎么调用呢?很简单的,一句代码搞定!


public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DefaultNavigationBar defaultNavigationBar= new DefaultNavigationBar.Build(this)
                                                    .setTitle("导航栏")
                                                    .setLeftText("返回").setLeftImageClickListener(new View.OnClickListener() {
                                                            @Override
                                                            public void onClick(View view) {
                                                                Toast.makeText(MainActivity.this, "点击了返回按钮", Toast.LENGTH_SHORT).show();
                                                            }
                                                        })
                                                    .builder();
    }
}

好了,以后不用再为修改头部烦恼了,一句代码搞定,觉得实用呢就试着用用~~

受辉哥的影响,学习了不少,大家可以去他的博客看看,很实用 @红橙Darren

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

推荐阅读更多精彩内容