Material Design之toolbar的自定义小封装

本文介绍了如何根据实际需求自定义Material Design的toolbar。针对复杂和通用的toolbar场景,分别提供了解决方案。文中详细讲解了如何创建自定义布局并添加到toolbar,以及封装一个可配置的toolbar组件,支持在XML和Java代码中控制点击事件。

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

1. 写在前面

最近看了很多toolbar的知识,但是感觉内容都大同小异,比如这个 还有这个 还有这个 而且对于实际项目并没有什么用,所以我自己总结下。先看图,这是大众点评里面的页面
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
其实很多app如果用到toolbar大致可以包含两种,一种是首页的toolbar非常复杂而且巧妙比如前面两张图,还有一种很简单,但是很多页面都用的着比如后面两张图。所以我认为:
1.如果是比较复杂的view,最好自己写个布局,然后添加到toolbar中,再在代码中设置到actionbar中。
2. 如果是用到地方比较多的toolbar布局,希望封装下,用的时候在xml布局中直接控制或者在java代码中代码控制,并且支持点击事件。
我下面的代码做的就是这两件事,先看下效果图。
这里写图片描述
这里写图片描述

2. 代码

a. 先看第一种情况吧,用起来比较简单,难的是将自己想要的复杂布局做出来,因为我这里只是举例子,所以布局比较简单。
因为我们是用toolbar代替了actionbar,所以theme那里需要一个不带actionbar的主题

 <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

因为我们需要将自己的布局添加到toolbar中,先看第一个页面xml图
这里写图片描述
这里面有几个需要注意的,

contentInsetStart

这个属性,因为我们添加一个布局到xml,如果不设置这个属性,当然也可以在代码中和theme中设置,如果不设置,里面的布局在toolbar中总会隔左边一段距离。如图
这里写图片描述
当我设置后,就会这样,所以这个属性很好理解见图
这里写图片描述
还有个需要注意的是,我这里需要使用include,这个无所谓,用不用,我这里只是试一试里面用include可不可以,因为我的项目中并没有用toolbar,感觉也方便不了多少,用include也可以实现自己想要的。include包含的布局代码如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:background="@color/colorAccent"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <ImageView
        android:src="@mipmap/back"
        android:layout_marginLeft="10dp"
        android:layout_centerVertical="true"
        android:layout_width="30dp"
        android:layout_height="30dp" />



    <TextView
        android:text="英雄连们"
        android:layout_centerInParent="true"
        android:textSize="18sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />



    <ImageView
        android:src="@mipmap/setting"
        android:layout_marginRight="10dp"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_width="30dp"
        android:layout_height="30dp" />

</RelativeLayout>

最后一个点需要注意的是这个高度height,因为我这里设置的是用actionbar自带的android高度,

android:layout_height="?attr/actionBarSize"

这个如果需要修改,直接去styles下面修改成自己想要的就是了,

 <item name="android:actionBarSize">自己填</item>

然后去activity中拿到toolbar,设置下就可以了,

 Toolbar toolbar = (Toolbar) this.findViewById(R.id.toolbar);
 setSupportActionBar(toolbar);

b. 现在就来看第二种情况,进行一个小小的封装,每个页面用时就是一个自定义的toolbar。


    <guozhaohui.com.customtoolbar.MyToolBar
        android:id="@+id/my_toolbar"
        app:iconRight="@mipmap/back"
        app:iconLeft="@mipmap/setting"
        app:textCen="地对地导弹"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize">

    </guozhaohui.com.customtoolbar.MyToolBar>

这里写图片描述
里面的三个app属性都是自定义的。前面这自定义步骤直接上代码了,自attrs中定义属性,继承toolbar,修改三个构造函数。

    <declare-styleable name="MyToolBar">

        <attr name="iconLeft" format="reference" />
        <attr name="textCen" format="string" />
        <attr name="iconRight" format="reference" />

    </declare-styleable>
 public MyToolBar(Context context) {
        this(context,null);
    }

    public MyToolBar(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public MyToolBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

假设这个简单模式的toolbar布局和刚才这个布局是一样的,因为确实差不多是这样的,所以我直接复制了一份include里面的布局,然后在MyToolbar代码中对他们初始化

 private void initView() {

        if(view==null){

            layoutInflater = LayoutInflater.from(getContext());
            view = layoutInflater.inflate(R.layout.item_toolbar, null);

            iv_toolbar_left = (ImageView) view.findViewById(R.id.iv_toolbar_left);
            tv_toolbar_cen = (TextView) view.findViewById(R.id.tv_toolbar_cen);
            iv_toolbar_right = (ImageView) view.findViewById(R.id.iv_toolbar_right);

            LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER_HORIZONTAL);
            addView(view,lp);

        }
    }

在然后通过TintTypedArray的对象对这三个自定义属性设置,

final TintTypedArray a = TintTypedArray.obtainStyledAttributes(getContext(), attrs,
                    R.styleable.MyToolBar, defStyleAttr, 0);

比如设置左边的icon

          //设置左边icon,其实toolbar有navigation这个属性可以用,但是为了更灵活,我们写自己的,可以随便调整
              Drawable leftIcon =  a.getDrawable(R.styleable.MyToolBar_iconLeft);
              if(leftIcon!=null){

//                  iv_toolbar_left.setBackground(leftIcon);
                  iv_toolbar_left.setImageDrawable(leftIcon);

              }

同理右边的icon也是一样的代码

     //同样,设置右边的icon
            Drawable rightIcon =  a.getDrawable(R.styleable.MyToolBar_iconRight);
            if(rightIcon!=null){
                iv_toolbar_right.setImageDrawable(rightIcon);
            }

设置中间文字

   //设置文字
            CharSequence cenText =   a.getText(R.styleable.MyToolBar_textCen);
            if(!TextUtils.isEmpty(cenText)){

                tv_toolbar_cen.setText(cenText);

            }

差不多完成了,在任何一个布局中想用的话直接用就可以了,刚才上面代码已经贴出来了,但是为了灵活一些。
在java代码中也能控制图标和文字,

  /**
     * 使可以在java代码中动态修改图标
     * @param iconRes
     */
    public void changeLeftIcon(int iconRes){

        if(iv_toolbar_left!=null){
            iv_toolbar_left.setImageDrawable(getResources().getDrawable(iconRes));
        }

    }

在activity中使用也比较简单,拿到myToolbar实例调用方法即可

  myToolBar.changeLeftIcon(R.mipmap.back);
  myToolBar.changeRightIcon(R.mipmap.setting);
    /**
     * java 代码中支持toolbar中间的text的修改
     * @param text
     */
    public void setCenterText(String text){

        if(tv_toolbar_cen!=null){

            if(!TextUtils.isEmpty(text)){
                tv_toolbar_cen.setText(text);
            }

        }

    }

java代码中

  myToolBar.setCenterText("德玛西亚");

    /**
     * 为图标设置点击事件
     * @param listener
     */
    public void setLeftIconListener(View.OnClickListener listener){
        if(iv_toolbar_left!=null){
            iv_toolbar_left.setOnClickListener(listener);
        }
    }

java代码中,也是调用方法

    //点击事件
        myToolBar.setLeftIconListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(CustomActivity.this,"我是点击事件",Toast.LENGTH_SHORT).show();
            }
        });

到这里应该差不多了,在项目中应该可以可以使用。

3. 源码

点击,,,,,,

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值