Builder设计模式--NavigationBar的实现

本文介绍了一种使用Builder设计模式创建NavigationBar的方法,该方法避免了在XML布局中编写标题栏,使得参数构建过程更加简单直观。通过实例化NavigationBar对象并设置参数,可以轻松创建具有不同功能的导航栏。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在应用程序中肯定会有标题栏,一般就是左边一个返回,一个标题,右边一个图片或者文字,不过有时候也会碰到中间是搜索框的情况,实现方式也很多,自定view、include、直接在xml布局中通过findViewById写等方式;这里是采用Builder设计模式打造一个NavigationBar,不需要在xml布局中去写,在activity初始化标题或者控件的地方实例一个NavigationBar对象并设置相应的参数就可以了。

Builder设计模式是一种比较常见的设计模式,Dialog等源码,Okhttp等第三方框架中都有使用到;

Builder设计模式又称为建造者模式,将建造过程与表示过程相分离,让(参数)构建过程变得更加简单和直观。

在Builder设计模式中普遍会采用链式调用的方式,但是需要注意,链式调用并不是Builder设计模式,链式调用这是一种调用方式;链式调用有一个体现,就是在调用方法的时候返回自身对象,Builder 一般也有一种体现,就是一般都会出现 Builder 对象。

创建一个接口,接口提供一个创建NavigationBar、绑定参数、添加到布局中的方法,让构造类去实现它;

public interface INavigation {
    /**
     * 创建navigationbar
     */
    void createNavigationBar();

    /**
     * 绑定navigationbar参数
     */
    void attachNavigationParmas();

    /**
     * 将navigationBar添加到父布局中
     * @param navigationView
     * @param parent
     */
    void attachParent(View navigationView, ViewGroup parent);
}
public class AbsNavigationBar<T extends AbsNavigationBar.Builder> implements INavigation {
    private T mBuilder;
    private View mNavigationView;

    protected AbsNavigationBar(T builder) {
        this.mBuilder = builder;
        createNavigationBar();
    }

    @Override
    public void createNavigationBar() {
        mNavigationView = LayoutInflater.from(mBuilder.mContext).inflate(mBuilder.mLayoutId, mBuilder.mParent, false);
        //添加
        attachParent(mNavigationView, mBuilder.mParent);
        //添加参数
        attachNavigationParmas();
    }

    @Override
    public void attachNavigationParmas() {
        Map<Integer, CharSequence> textMap = mBuilder.textMap;
        for(Map.Entry<Integer, CharSequence> texts:textMap.entrySet()){
            TextView textView = findViewById(texts.getKey());
            textView.setText(texts.getValue());
        }
        Map<Integer, View.OnClickListener> clicks = mBuilder.clicks;
        for(Map.Entry<Integer, View.OnClickListener> click:clicks.entrySet()){
            View view = findViewById(click.getKey());
            view.setOnClickListener(click.getValue());
        }
    }

    public <T extends View> T findViewById(int viewId) {
        return (T) mNavigationView.findViewById(viewId);
    }

    /**
     * 返回 Builder
     *
     * @return
     */
    public T getBuilder() {
        return mBuilder;
    }

    @Override
    public void attachParent(View navigationView, ViewGroup parent) {
        parent.addView(navigationView, 0);
    }

    public static abstract class Builder<T extends Builder> {
        public Context mContext;
        public int mLayoutId;
        public ViewGroup mParent;
        //存储对应id的文本
        public Map<Integer, CharSequence> textMap;
        //存储对应id的点击事件
        public Map<Integer, View.OnClickListener> clicks;

        public Builder(Context context, int layoutId) {
            this.mContext = context;
            this.mLayoutId = layoutId;
            Activity activity = (Activity) context;
            ViewGroup viewGroup = (ViewGroup) activity.getWindow().getDecorView();
            this.mParent = (ViewGroup) viewGroup.getChildAt(0);
            textMap = new HashMap<>();
            clicks = new HashMap<>();
        }

        /**
         * 设置左边文字
         *
         * @param leftId
         * @param leftText
         * @return
         */
        public T setLeftText(int leftId, String leftText) {
            textMap.put(leftId, leftText);
            return (T) this;
        }

        /**
         * 设置中间文字
         *
         * @param middleId
         * @param middleText
         * @return
         */
        public T setMiddleText(int middleId, String middleText) {
            textMap.put(middleId, middleText);
            return (T) this;
        }

        /**
         * 设置右边文字
         *
         * @param rightId
         * @param rightText
         * @return
         */
        public T setRightText(int rightId, String rightText) {
            textMap.put(rightId, rightText);
            return (T) this;
        }

        /**
         * 左边点击事件
         *
         * @param leftId
         * @param listener
         * @return
         */
        public T setLeftClick(int leftId, View.OnClickListener listener) {
            clicks.put(leftId, listener);
            return (T) this;
        }

        /**
         * 右边点击事件
         *
         * @param rightId
         * @param listener
         * @return
         */
        public T setRightClick(int rightId, View.OnClickListener listener) {
            clicks.put(rightId, listener);
            return (T) this;
        }

        /**
         * 用来创建 NavigationBar
         *
         * @return
         */
        public abstract AbsNavigationBar create();
    }
}

在Builder构造方法中通过上下文强转成Activity,通过当前的Activity获取到DecorView将NavigationBar添加到DecorView布局容器中,这样就不需要在使用Activity中取进行添加;Builder中提供一些设置参数的方法,在attachNavigationParmas方法中进行参数的绑定;因为Builder是一个静态抽象类,所以在使用的时候要定义一个具体的NavigationBar继承自AbsNavigationBar;

public class NavigationBar extends AbsNavigationBar{
    protected NavigationBar(Builder builder) {
        super(builder);
    }
    public static class Builder extends AbsNavigationBar.Builder<NavigationBar.Builder>{

        public Builder(Context context, int layoutId) {
            super(context, layoutId);
        }

        @Override
        public NavigationBar create() {
            return new NavigationBar(this);
        }
    }
}

这样就构建好了,实例化一个NavigationBar对象并设置相应的参数;

NavigationBar navigationBar=new NavigationBar.Builder(this,R.layout.navigation_layout)
                .setLeftText(R.id.tv_left,"返回")
                .setMiddleText(R.id.tv_title,"首页")
                .setRightText(R.id.tv_right,"保存")
                .setLeftClick(R.id.tv_left, new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(MainActivity.this,"返回",Toast.LENGTH_LONG).show();
                    }
                })
                .setRightClick(R.id.tv_right, new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(MainActivity.this,"保存",Toast.LENGTH_LONG).show();
                    }
                })
                .create();

这样就创建了一个NavigationBar,但是在每次设置参数的时候都需要传入一个对应的控件id,还是蛮繁琐的,可以根据项目的需要创建一个公用的NavigationBar,如果差异比较大的话,根据当前页面的需求有选择的创建对应的NavigationBar;

public class DefaultNavigationBar extends AbsNavigationBar<DefaultNavigationBar.Builder>{
    protected DefaultNavigationBar(Builder builder) {
        super(builder);
    }

    @Override
    public void attachNavigationParmas() {
        super.attachNavigationParmas();
        //绑定参数
    }

    public static class Builder extends AbsNavigationBar.Builder<DefaultNavigationBar.Builder>{
        public Builder(Context context) {
            super(context, R.layout.navigation_layout);
        }

        @Override
        public DefaultNavigationBar create() {
            return new DefaultNavigationBar(this);
        }
        /**
         * 设置左边文字
         *
         * @param leftText
         * @return
         */
        public Builder setLeftText(String leftText) {
            if(leftText==null||leftText.length()==0){
                leftText="返回";
            }
            setLeftText(R.id.tv_left,leftText);
            return this;
        }

        /**
         * 设置中间文字
         *
         * @param middleText
         * @return
         */
        public Builder setMiddleText(String middleText) {
            setMiddleText(R.id.tv_title,middleText);
            return this;
        }

        /**
         * 设置右边文字
         *
         * @param rightText
         * @return
         */
        public Builder setRightText(String rightText) {
            setRightText(R.id.tv_right,rightText);
            return this;
        }

        /**
         * 左边点击事件
         *
         * @param listener
         * @return
         */
        public Builder setLeftClick(View.OnClickListener listener) {
            setLeftClick(R.id.tv_left,listener);
            return this;
        }

        /**
         * 右边点击事件
         *
         * @param listener
         * @return
         */
        public Builder setRightClick(View.OnClickListener listener) {
            setRightClick(R.id.tv_right,listener);
            return this;
        }
    }
}

这样子实例化NavigationBar时就不需要每次都传入一个控件id;

DefaultNavigationBar navigationBar=new DefaultNavigationBar.Builder(this)
                .setMiddleText("首页")
                .setRightText("保存")
                .setLeftClick(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(MainActivity.this,"返回",Toast.LENGTH_LONG).show();
                    }
                })
                .setRightClick(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(MainActivity.this,"保存",Toast.LENGTH_LONG).show();
                    }
                })
                .create();

如果需要对NavigationBar中的一些特殊的控件做处理,可以通过实例化好的NavigationBar.findViewById()获取对应的控件进行处理;

TextView leftView = (TextView) navigationBar.findViewById(R.id.tv_left);
leftView.setText("首页返回");

源码

内容概要:本文探讨了在MATLAB/SimuLink环境中进行三相STATCOM(静态同步补偿器)无功补偿的技术方法及其仿真过程。首先介绍了STATCOM作为无功功率补偿装置的工作原理,即通过调节交流电压的幅值和相位来实现对无功功率的有效管理。接着详细描述了在MATLAB/SimuLink平台下构建三相STATCOM仿真模型的具体步骤,包括创建新模型、添加电源和负载、搭建主电路、加入控制模块以及完成整个电路的连接。然后阐述了如何通过对STATCOM输出电压和电流的精确调控达到无功补偿的目的,并展示了具体的仿真结果分析方法,如读取仿真数据、提取关键参数、绘制无功功率变化曲线等。最后指出,这种技术可以显著提升电力系统的稳定性与电能质量,展望了STATCOM在未来的发展潜力。 适合人群:电气工程专业学生、从事电力系统相关工作的技术人员、希望深入了解无功补偿技术的研究人员。 使用场景及目标:适用于想要掌握MATLAB/SimuLink软件操作技能的人群,特别是那些专注于电力电子领域的从业者;旨在帮助他们学会建立复杂的电力系统仿真模型,以便更好地理解STATCOM的工作机制,进而优化实际项目中的无功补偿方案。 其他说明:文中提供的实例代码可以帮助读者直观地了解如何从零开始构建一个完整的三相STATCOM仿真环境,并通过图形化的方式展示无功补偿的效果,便于进一步的学习与研究。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值