思路
套用之前的builder设计模式的思路
Product(NavigationBar)+Builder+Parameter
效果:

mainActivity代码

    @Overrideprotected void initTitle() {new DefaultNavigationBar.Builder(this).setTitle("投稿").setRightIcon(R.mipmap.ic_launcher).setRightText("右边").setRightClickListener(v -> Toast.makeText(MainActivity.this, "右边", Toast.LENGTH_SHORT).show()).builder();}

DefaultNavigationBar

public class DefaultNavigationBar<D extendsDefaultNavigationBar.Builder.DefaultNavigationParams> extendsAbsNavigationBar<DefaultNavigationBar.Builder.DefaultNavigationParams> {public DefaultNavigationBar(Builder.DefaultNavigationParams params) {super(params);}@Overridepublic int bindLayoutId() {// 默认title bar布局return R.layout.title_bar;}@Overridepublic void applyView() {// 应用效果setText(R.id.title, getParams().mTitle);setText(R.id.right_text, getParams().mRightText);setOnClickListener(R.id.right_text, getParams().mRightClickListener);// 默认左边button是返回button 作用为finishActivitysetOnClickListener(R.id.back, getParams().mLeftClickListener);}public static class Builder extends AbsNavigationBar.Builder {DefaultNavigationParams P;public Builder(Context context, ViewGroup parent) {super(context, parent);P = new DefaultNavigationParams(context, parent);}public Builder(Context context) {super(context, null);P = new DefaultNavigationParams(context, null);}@Overridepublic DefaultNavigationBar builder() {return new DefaultNavigationBar(P);}// 存储所有效果到DefaultNavigationParamspublic Builder setTitle(String title) {P.mTitle = title;return this;}// 存储右边的文字public Builder setRightText(String rightText) {P.mRightText = rightText;return this;}// 存储右边的点击事件public Builder setRightClickListener(View.OnClickListener rightListener) {P.mRightClickListener = rightListener;return this;}// 存储左边的点击事件public Builder setLeftClickListener(View.OnClickListener rightListener) {P.mLeftClickListener = rightListener;return this;}// 存储右边的图片public Builder setRightIcon(int rightRes) {P.mRightImageId = rightRes;return this;}public static class DefaultNavigationParams extendsAbsNavigationParams {// 存储所有可控制navigationBar的变量public String mTitle;public String mRightText;public View.OnClickListener mRightClickListener;public View.OnClickListener mLeftClickListener = v -> {// 关闭当前Activity((Activity) mContext).finish();};public int mRightImageId;public DefaultNavigationParams(Context context, ViewGroup parent) {super(context, parent);}}}
}

DefaultNavigationParams P;在Builder的构造方法初始化
之后通过各种set方法将属性存放到DefaultNavigationParams
builder方法返回DefaultNavigationBar对象 同时在基类中进行mParams的赋值 createAndBind调用
createAndBind中第一步找到DecorView的第一个子布局 该布局就是navigationBar的父容器
具体参见:
https://blog.csdn.net/u011109881/article/details/111085949
的这张图片

第二步调用applyView将之前各种set方法设置的属性值应用在NavigationBar上

public abstract class AbsNavigationBar<P extends AbsNavigationBar.Builder.AbsNavigationParams> implements INavigationBar {//此处使用泛型 外部传入的参数params有可能是AbsNavigationBar.Builder.NavigationParams的子类(在AbsNavigationBar的具体实现类中)private static final String TAG = "AbsNavigationBar";// 存储默认的配置参数private P mParams;// 存放navigationBar的布局private View mNavigationView;public AbsNavigationBar(P params) {this.mParams = params;createAndBind();}//根据viewId查找导航条上显示的Stringpublic String getString(int viewId) {return this.mParams.mContext.getResources().getString(viewId);}//根据viewId查找导航条上显示的颜色public int getColor(int viewId) {return ContextCompat.getColor(this.mParams.mContext, viewId);}public P getParams() {return mParams;}// 设置文本public void setText(int viewId, CharSequence text) {// 每次都 findViewById   减少findViewById的次数View view = mNavigationView.findViewById(viewId);if (view != null) {try {//利用反射使得所有带有setText(CharSequence)的方法的控件都可以调用setText的方法Class clazz = view.getClass();Method setTextMethod = clazz.getMethod("setText", CharSequence.class);setTextMethod.invoke(view, text);view.setVisibility(View.VISIBLE);} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {Log.e(TAG, "setText: error " + e.getMessage());e.printStackTrace();}}}// 设置点击事件public void setOnClickListener(int viewId, View.OnClickListener listener) {View view = mNavigationView.findViewById(viewId);if (view != null) {view.setOnClickListener(listener);}}// 设置图片public void setImageResource(int viewId, int resourceId) {ImageView imageView = mNavigationView.findViewById(viewId);if (imageView instanceof ImageView) {imageView.setImageResource(resourceId);}else{Log.e(TAG, "设置图片失败");}}/*** 创建和绑定布局*/public void createAndBind() {if(mParams.mParent == null){// 获取DecorViewViewGroup activityRoot = (ViewGroup) ((Activity) mParams.mContext).getWindow().getDecorView();// 获取navigationBar的父容器viewGroup(R.id.content的父布局)mParams.mParent = (ViewGroup) activityRoot.getChildAt(0);}if(mParams.mParent == null){Log.e(TAG, "导航条的布局为空");return;}// 填充navigationBarmNavigationView = LayoutInflater.from(mParams.mContext).inflate(bindLayoutId(), mParams.mParent, false);// 将布局添加到parent的头部mParams.mParent.addView(mNavigationView, 0);applyView();}// 用于构建导航条类 这个类只是定义默认的配置 具体功能的实现由具体的实现类决定public abstract static class Builder {// 构造方法public Builder(Context context, ViewGroup parent) {}// 创建导航条方法public abstract AbsNavigationBar builder();// NavigationParams用于存储默认的配置参数public static abstract class AbsNavigationParams {public Context mContext;// NavigationBar显示的父布局public ViewGroup mParent;public AbsNavigationParams(Context context, ViewGroup parent) {this.mContext = context;this.mParent = parent;}}}
}

INavigationBar的定义

interface INavigationBar {// 绑定布局IDint bindLayoutId();// 给View设置参数void applyView();
}

主体部分就这么多 其他一些资源文件如下
navigationBar默认布局layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"style="@style/title_bar_style"><ImageViewandroid:layout_centerVertical="true"android:id="@+id/back"style="@style/back_view" /><TextViewandroid:id="@+id/title"style="@style/title_text_style"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:ellipsize="end"android:singleLine="true"android:visibility="gone"/><TextViewandroid:id="@+id/right_text"android:visibility="gone"style="@style/title_bar_button"android:layout_alignParentRight="true" />
</RelativeLayout>

各个style

<?xml version="1.0" encoding="utf-8"?>
<resources><style name="title_bar_style"><item name="android:background">@color/title_bar_bg_day</item><item name="android:paddingLeft">0.0dip</item><item name="android:paddingRight">0.0dip</item><item name="android:layout_width">fill_parent</item><item name="android:layout_height">44.0dip</item></style><style name="title_text_style"><item name="android:textSize">18.0sp</item><item name="android:textColor">@color/s9</item></style><style name="title_bar_button"><item name="android:textSize">16.0sp</item><item name="android:textColor">@color/s9</item><item name="android:gravity">center</item><item name="android:background">@null</item><item name="android:paddingLeft">5.0dip</item><item name="android:paddingRight">5.0dip</item><item name="android:layout_width">wrap_content</item><item name="android:layout_height">fill_parent</item><item name="android:layout_marginLeft">0.0dip</item><item name="android:layout_marginRight">10.0dip</item></style><style name="back_view" parent="@style/title_bar_button"><item name="android:layout_height">wrap_content</item><item name="android:gravity">center</item><item name="android:background">@drawable/btn_back</item><item name="android:paddingLeft">0.0dip</item><item name="android:paddingRight">0.0dip</item><item name="android:layout_marginLeft">0.0dip</item><item name="android:layout_marginRight">0.0dip</item><item name="android:text">@null</item><item name="android:drawableLeft">@null</item></style>
</resources>

返回键的资源

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:drawable="@drawable/ic_back_pressed" android:state_pressed="true" /><item android:drawable="@drawable/ic_back_pressed" android:state_enabled="false" /><item android:drawable="@drawable/ic_back_normal" />
</selector><vector xmlns:android="http://schemas.android.com/apk/res/android"android:width="24dp"android:height="24dp"android:viewportWidth="24"android:viewportHeight="24"android:tint="?attr/colorControlNormal"><pathandroid:fillColor="#999"android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z" />
</vector><vector xmlns:android="http://schemas.android.com/apk/res/android"android:width="24dp"android:height="24dp"android:viewportWidth="24"android:viewportHeight="24"android:tint="?attr/colorControlActivated"><pathandroid:fillColor="#FFF"android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z" />
</vector>

红橙Darren视频笔记 builder设计模式+navigationBar导航条相关推荐

  1. 红橙Darren视频笔记 builder设计模式 navigationbar 导航栏第二版

    1.builder设计模式简介 builder的实际应用的典型案例有AlertDialog和OKHttp 例如 // AlertDialogAlertDialog alertDialog = new ...

  2. 红橙Darren视频笔记 UML图简介

    整体架构复制自红橙原视频的课堂笔记 因为他这一课没有博客,所以没有转载链接,CSDN没有转载地址是无法作为转载类型的文章发表的,暂时标记为原创 参考链接 https://blog.csdn.net/r ...

  3. 红橙Darren视频笔记 代理模式 动态代理和静态代理

    红橙Darren视频笔记 代理模式 动态代理和静态代理(Android API 25) 关于代理模式我之前有过相关的介绍: https://blog.csdn.net/u011109881/artic ...

  4. 红橙Darren视频笔记 类加载机制(API28) 自己写个热修复 查看源码网站

    第一部分 类加载机制 一个Activity是如何被Android虚拟机找到的? 在之前的文章 红橙Darren视频笔记 自定义View总集篇(https://blog.csdn.net/u011109 ...

  5. 红橙Darren视频笔记 利用阿里巴巴AndFix进行热修复

    注意 由于AndFix在2017年左右就停止更新了,在最新版本的apk上遇到很多问题,我最终也没有成功进行热修复.本节主要是学习热修复的原理 在上一篇 红橙Darren视频笔记 自己捕获异常并保存到本 ...

  6. 红橙Darren视频笔记 Behavior的工作原理源码分析

    主要coordinatorlayout的代码来自coordinatorlayout-1.0.0-sources.jar 本文从源码介绍 CoordinatorLayout 的 behavior 怎么工 ...

  7. 红橙Darren视频笔记 仿QQ侧滑效果

    这一篇没有什么新的内容 就是改写 红橙Darren视频笔记 仿酷狗侧滑效果 的侧滑的效果 1.去掉淡入淡出效果 2.加上黑色模板效果 效果: 去掉淡入淡出效果很简单 就是注释掉onScrollChan ...

  8. 红橙Darren视频笔记 ViewGroup事件分发分析 基于API27

    本节目标,通过案例,先看程序运行结果,然后跟踪源码,理解为什么会有这样的输出,继而理解view group的分发机制,感觉和证明题很像呢. 考虑以下程序的运行结果: case1: public cla ...

  9. 红橙Darren视频笔记 万能Dialog builder设计模式

    1.Android原生的AlertDialog 我们今天看一下AlertDialog的创建方式以及它使用到的builder设计模式 我们先看看原生Android的AlertDialog创建方式: Al ...

最新文章

  1. 记录两段经典标定代码
  2. 解决升级 Office 2010 之后 Outlook 提示“无法打开 Microsoft Outlook”
  3. httpd设置HTTPS双向认证
  4. 解决Cacti监控图像断断续续问题
  5. Midletinfo-探索手机javaME系统信息的实用工具
  6. Android实现计算器布局(表格布局)
  7. 社会工程学之《反欺骗的艺术》小结(三)
  8. 测试金士顿固态硬盘软件,金士顿固态硬盘优化工具(Kingston Toolbox)
  9. 必须收藏!130 个相见恨晚的超实用网站,一次性分享出来
  10. 汇编 十六进制转二进制
  11. android模拟器虚拟机的下载、安装和使用
  12. 解决Java下载Zip压缩文件,解压后报不可预料的压缩文件末端
  13. 两个次序统计量的联合密度函数
  14. 安信天行全方位信息安全态势感知平台建设与运营
  15. springboot整合logback日志
  16. ESP32开发路程——环境搭建、引脚、烧录、UART、ADC、WS2812、RFID、DAC、FreeRTOS、CJSON
  17. 无光照渲染shader-二次元
  18. URI RUL和URN的区别(看不懂?)
  19. 蓝图(Blueprint)理解
  20. 推荐三个 VSCode 摸鱼插件

热门文章

  1. linux 根目录分配多少好,Linux下硬盘怎么分区才合适:根分区(/)交换分区(/swap)和/boot分区需要多大...
  2. 《网络对抗》Exp5 MSF基础应用
  3. IntelliJ IDEA 2017新工具
  4. Linux下能访问Nginx,本地无法访问
  5. 检测文件是否有BOM 头,并删除BOM头(php)
  6. [SQL] 常用查询脚本
  7. 《Programming with Objective-C》第四章 Encapsulating Data
  8. Android 之 Window、WindowManager 与窗口管理
  9. Asp.net(c#)GridView分页时用图片显示上一页,下一页
  10. C语言课后习题(44)