android 使用Builder设计模式,设计ToolBar

使用Builder设计模式,设计ToolBar

Builder设计模式解析

android也有不地方采用了Builder设计模式的,比如NotificationCompat.Builder和AlertDialog.Builder就采用了Builder的设计模式

最典型的代码示例

NotificationCompat.Builder

NotificationCompat.Builder mBuilder =
        new NotificationCompat.Builder(this)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!");
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(this, ResultActivity.class);

// The stack builder object will contain an artificial back stack for the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
        stackBuilder.getPendingIntent(
            0,
            PendingIntent.FLAG_UPDATE_CURRENT
        );
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(mId, mBuilder.build());

AlertDialog.Builder

AlertDialog.Builder builder2=new AlertDialog.Builder(
getActivity(),R.style.AppTheme_NoActionBar);

        builder2.setTitle("警告")
        .setMessage("你确定删除吗")
        new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog,
             int which) {
                ToastUtil.showToast(getActivity(),"你点击了取消");
            }
        })
         .setPositiveButton("确定", 
         new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, 
                    int which) {
                        ToastUtil.showToast(getActivity(),
                        "你点击了确定");
                    }
          }) .create().show();

Builder设计模式的特点

参数化

AlertDialog.Builder里面会实例一个AlertController.AlertParams,里面包含大部分,创建AlertDialog的参数,实现功能的参数化

public Builder(Context context, int themeResId) {

 P = new AlertController.AlertParams(new ContextThemeWrapper(context, resolveDialogTheme(context, themeResId)));
        }

可维护性强

由于Builder设计模式的参数,达到功能的多变,可维护性就变得很强
例如:可以 调用setMessage(“你确定删除吗”),也可以去掉

ToolBar的设计,抽象化

接口抽象toolbar的规范public interface INavigation


/**
 * 所有Toolbar的规范
 * 抽象一个Toolbar
 * 
 * Created by 辉神 on 2016/8/10.
 */

public interface INavigation {
    /**
     * 定义布局(返回布局id)
     * @return
     */
    public int bindLayoutId();

    /**
     * 创建和绑定布局
     */
    public void build();
}

抽象并实现INavigation——public abstract class AbsNavigation

/**
 * 再次抽象Toolbar
 * -只要是app的开发,都会有布局的创建和绑定
 * -再次抽象,是为了,下次使用时,不用再次创建布局和绑定
 * Created by 辉神 on 2016/8/10.
 */

public abstract class AbsNavigation<P extends AbsNavigation.NavigationParams> implements INavigation {
    /**
     *     设置一个默认LayoutId,默认为0
     */
    private static final  int DEFAULT_LAYOUT_ID=0;
    private P params;
    private View contentView;

    public AbsNavigation(P params) {
        this.params = params;
    }

    public P getParams() {
        return  params;
    }

    @Override
    public int bindLayoutId() {
        return DEFAULT_LAYOUT_ID;
    }

    @Override
    public void build() {
        //创建和绑定布局
        if (contentView==null)
        contentView = bindParent(bindLayoutId(), ((NavigationParams)getParams()).parent);
    }

    /**
     * 方便子类使用
     * @param id
     * @return
     */
    public View findLayoutById(int id){
        return contentView!=null?contentView.findViewById(id):null;
    }
    public String getString(int id){
        return contentView.getContext().getResources().getString(id);
    }

    public View bindParent(int id, ViewGroup parent) {
        //先要判断这个id是否为0
        if (id==DEFAULT_LAYOUT_ID){
            return null;
        }
        View childView = ((NavigationParams)getParams()).inflater.inflate(id, parent,false);
        return bindParent(childView,parent);
    }

    public View bindParent(View childView, ViewGroup parent) {
        ViewGroup viewParent= (ViewGroup) childView.getParent();
        //如果他原来有一个爸爸了,就先把它爸爸干掉
        if(viewParent!=null){
            viewParent.removeView(childView);
        }
        //添加我们的爸爸给这个视图,因为一个视图不可能有两个爸爸
        parent.addView(childView,0);
        //将爸爸返回
        return parent;
    }

    /**
     * Builder设计模式,所有Toolbar都必须有的参数----------参数集(参数类)
     */
    public static class NavigationParams{
        private Context context;//上下文对象,用于加载布局视图
        private ViewGroup parent;//每一个布局视图都有一个爸爸
        private LayoutInflater inflater;
        public NavigationParams(Context context, ViewGroup parent) {
            this.context = context;
            this.parent = parent;
            inflater=inflater.from(context);
        }
    }

    /**
     * 创建Toolbar
     */
    public abstract static class Builder{
        public Builder(Context context,ViewGroup parent) {
        }

        /**
         * 创建Toolbar
         * @return
         */
        public abstract INavigation create();
    }
}

搭建toolbar布局框架——abstract class DefaultNavigation(多个子类(功能)继承此父类,功能需求就可以多变)

/**
 * 左中右场场景,
 * 也就是先设置左中右的布局,子类可以实现更多内容
 * Created by 辉神 on 2016/8/11.
 */

public abstract class DefaultNavigation<P extends AbsNavigation.NavigationParams> extends AbsNavigation<P> {

    public DefaultNavigation(P params) {
        super(params);
    }

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

    @Override
    public void build() {
        super.build();//一定要super,因为要绑定左中右的父容器

        //初始化父容器,布局框架
        LinearLayout ll_left= (LinearLayout) findLayoutById(R.id.ll_left);
        LinearLayout ll_center= (LinearLayout) findLayoutById(R.id.ll_center);
        LinearLayout ll_right= (LinearLayout) findLayoutById(R.id.ll_right);

        //以下方法都是抽象,显然,子类可以任意定义布局,达到动态改变,方便维护
        //绑定布局也就是,将子布局添加到当前这个“左中右场景”中来
        bindParent(bindLeftLayoutId(),ll_left);
        bindParent(bindCenterLayoutId(),ll_center);
        bindParent(bindRightLayoutId(),ll_right);
        //初始化子布局
        initLeftLayout(ll_left);
        initCenterLayout(ll_center);
        initRightLayout(ll_right);

    }

    /**
     *返回左边布局ID—— 用于子布局(待子类实现)
     * @return ID
     */
    public abstract int bindLeftLayoutId();

    /**
     * 返回中间布局ID—— 用于子布局(待子类实现)
     * @return ID
     */
    public abstract int bindCenterLayoutId();

    /**
     * 返回右边布局ID—— 用于子布局(待子类实现)
     * @return ID
     */
    public abstract int bindRightLayoutId();

    /**
     * 初始化左边的布局—— 用于子布局(待子类实现)
     * @param view
     * @return
     */
    public abstract void initLeftLayout(View view);
    /**
     * 初始化中间的布局—— 用于子布局(待子类实现)
     * @param view
     * @return
     */
    public abstract void initCenterLayout(View view);
    /**
     * 初始化右边的布局—— 用于子布局(待子类实现)
     * @param view
     * @return
     */
    public abstract void initRightLayout(View view);
}

主页toolbar的实现——HomeNavigation

/**
 * 默认的主页toolbar实现
 * Created by 辉神 on 2016/8/11.
 */

public class HomeNavigation extends DefaultNavigation<HomeNavigation.HomeNavigationParams> {

    public HomeNavigation(HomeNavigationParams params) {
        super(params);
    }

    /**
     * 设置默认主页的参数
     */
    public static class HomeNavigationParams extends AbsNavigation.NavigationParams{
        public int leftImageRes;
        public int centerTitleRes;
        public int rightImageRes;
        public int rightTextRes;

        public View.OnClickListener leftOnclickListener;
        public View.OnClickListener rightOnClickListener;

        public HomeNavigationParams(Context context, ViewGroup parent) {
            super(context, parent);
        }
    }

    /**
     * 构建我们的Toolbar
     * @return
     */
    public static class Builder extends AbsNavigation.Builder{
        private HomeNavigationParams p;

        public Builder(Context context, ViewGroup parent) {
            super(context, parent);
            this.p=new HomeNavigationParams(context,parent);
        }
        /**
         *  设置左边的图片
         */
        public Builder setLeftImageRes(int leftImageRes){
            this.p.leftImageRes=leftImageRes;
            return this;
        }

        /**
         * 设置中间标题
         * @param centerTitleRes
         * @return
         */
        public Builder setCenterTitleRes(int centerTitleRes){
            this.p.centerTitleRes=centerTitleRes;
            return this;
        }

        /**
         * 设置右边图片
         * @param rightImageRes
         * @return
         */
        public Builder setRightImageRes(int rightImageRes){
            this.p.rightImageRes=rightImageRes;
            return this;
        }

        /**
         * 设置右边文字
         * @param rightTextRes
         * @return
         */
        public Builder setRightTextRes(int rightTextRes){
            this.p.rightTextRes=rightTextRes;
            return this;
        }

        /**
         * 设置左边监听事件
         * @param leftOnclickListener
         * @return
         */
        public Builder setLeftOnclickListener(View.OnClickListener leftOnclickListener){
            this.p.leftOnclickListener=leftOnclickListener;
            return this;
        }

        /**
         * 设置右边监听事件
         * @param rightOnClickListener
         * @return
         */
        public Builder setRightOnClickListener(View.OnClickListener rightOnClickListener){
            this.p.rightOnClickListener=rightOnClickListener;
            return this;
        }

        /**
         * <p>这个方法被调用了之后,还没有结束,还需要调用接口中的build()方法</p>
         * <p>HomeNavigation的是上层父类,是INavigation的实现类,</p>
         * <p>所以当前INavigation的build()方法被调用时,也就相当于接口回调了,builder设计模式也就完成</p>
         * <p>用户还需要再调用最高层接口,已经设计好的方法build()方法</p>
         * <p>这个builder设计模式简直屌炸天</p>
         * @return
         */
        @Override
        public INavigation create() {
            return new HomeNavigation(p);
        }
    }

    @Override
    public int bindLayoutId() {
        return super.bindLayoutId();
    }

    @Override
    public int bindLeftLayoutId() {
        return R.layout.navigation_default_left;
    }

    @Override
    public int bindCenterLayoutId() {
        return R.layout.navigation_default_center;
    }

    @Override
    public int bindRightLayoutId() {
        return R.layout.navigation_home_right;
    }

    @Override
    public void initLeftLayout(View view) {
        ImageView iv_default_left = (ImageView) view.findViewById(R.id.iv_default_left);
        iv_default_left.setImageResource(getParams().leftImageRes);
        iv_default_left.setOnClickListener(getParams().leftOnclickListener);
    }

    @Override
    public void initCenterLayout(View view) {
        TextView tv_default_center = (TextView) view.findViewById(R.id.tv_default_center);
        tv_default_center.setText(getString(getParams().centerTitleRes));
    }

    @Override
    public void initRightLayout(View view) {
        TextView tv_home_right = (TextView) view.findViewById(R.id.tv_home_right);
        tv_home_right.setText(getString(getParams().rightTextRes));
        tv_home_right.setOnClickListener(getParams().rightOnClickListener);
        ImageView iv_home_right= (ImageView) view.findViewById(R.id.iv_home_right);
        iv_home_right.setImageResource(getParams().rightImageRes);
        //启动金币动画
        AnimationDrawable animationDrawable= (AnimationDrawable) iv_home_right.getBackground();
        animationDrawable.start();
    }
}

HomeNavigation的调用,即实例化

private void initNavigation(View contentView) {

HomeNavigation.Builder builder=new HomeNavigation.Builder
(getActivity(), (ViewGroup) contentView);

        builder.setLeftImageRes(R.mipmap.apk_all_top_nav)
                .setCenterTitleRes(R.string.tabbar_home_text)
                .setRightTextRes(R.string.nav_sign_in)
                .setRightImageRes(R.drawable.anim_sign_coin)
                .setLeftOnclickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                     ToastUtil .showToast(getActivity(),
                     "点击了菜单");
                    }
                })
                .setRightOnClickListener
                (new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        ToastUtil.showToast(getActivity(),
                        "点击了签到");
                    }
                })
                .create().build();

    }

主页toolbar实现效果

这里写图片描述

布局代码就不给了

posted @ 2016-08-12 01:58  iszengmh  阅读(122)  评论(0编辑  收藏  举报