BaseActivity中封装通用的Toolbar

之前写过一篇关于如何使用Toolbar的文章,最近在搭建新项目时对Toolbar做了封装。封装的预期目标是只在BaseActivity中引入Toolbar,然后子Activity通过继承BaseActivity就能显示Toolbar。接下来就看看如何实现这样的功能。 
因为我们使用toolbar作为titlebar,因此首先需要去掉Actionbar。在style文件下修改默认Theme的parent为Theme.AppCompat.Light.NoActionBar便可以去掉默认的Actionbar,如下:

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

然后定义一个toolbar_layout的xml文件,在toolbar中加入俩个TextView作为标题和子标题,如下:

<android.support.v7.widget.Toolbar    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimary"
    android:minHeight="?attr/actionBarSize">
    <!--自定义toolbar的title 和subtitle -->
    <TextView        android:id="@+id/tv_right"
        style="@style/TextAppearance.AppCompat.Widget.ActionBar.Subtitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:maxLines="1"
        android:textColor="@color/white"
        android:text="right"
        android:paddingRight="10dp"
        android:layout_gravity="right" />

    <TextView        android:id="@+id/tv_title"
        style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:lines="1"
        android:ellipsize="end"
        android:text="title"
        android:scrollHorizontally="true"
        android:textColor="@color/white"
        android:layout_gravity="center" /></android.support.v7.widget.Toolbar>
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

  • 28

  • 29

  • 30

  • 31

  • 32

接着在BaseActivity的布局文件中include进toolbar_layout,如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <include layout="@layout/toolbar_layout"/></LinearLayout>
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

这样BaseActivity中就可以正常显示出Toolbar了。那么如何实现子Activity继承BaseActivity而显示toolbar呢?其实我们可以在BaseActivity中做文章。 
首先在BaseActivity中声明一个LinearLayout,然后把BaseActivity的布局文件添加到该LinearLayout中。我们知道子Activity通过setContentView()方法来关联布局文件,因此我们可以在BaseActivity中去重写setContentView()方法,在重写的setContentView中把子类的布局文件也添加到事先声明的LinearLayout中,接下来应该解决如何将这个LinearLayout与Activity关联。查阅相关资料可以知道,可以通过 findViewById(android.R.id.content)拿到window的ViewGroup然后将刚才声明的LinearLayout添加到这个ViewGroup中,这样就可以在子Activity中显示出BaseActivity中的Toolbar了。(具体原因可以查阅android.R.id.content和
DecorView)代码如下:

public abstract class BaseActivity extends AppCompatActivity{
     //the container of this activity layout and sub-activity layout
    private LinearLayout parentLinearLayout;    @Override
    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);
        initContentView(R.layout.activity_base);
        setContentView(getLayoutId());
        initToolBar();
        init();
    }//  overwrite the function in sub-activity and return the layout id of sub-activity   
 protected abstract int getLayoutId(); private void initContentView(@LayoutRes int layoutResID) {
        ViewGroup viewGroup = (ViewGroup) findViewById(android.R.id.content);
        viewGroup.removeAllViews();
        parentLinearLayout = new LinearLayout(this);
        parentLinearLayout.setOrientation(LinearLayout.VERTICAL);        //  add parentLinearLayout in viewGroup
        viewGroup.addView(parentLinearLayout);        //  add the layout of BaseActivity in parentLinearLayout
        LayoutInflater.from(this).inflate(layoutResID, parentLinearLayout, true);
    }   /**
     * @param layoutResID  layout id of sub-activity
     */
    @Override
    public void setContentView(@LayoutRes int layoutResID) {        //  added the sub-activity layout id in parentLinearLayout
        LayoutInflater.from(this).inflate(layoutResID, parentLinearLayout, true);

    }
}
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

  • 28

  • 29

  • 30

  • 31

  • 32

  • 33

  • 34

  • 35

  • 36

上述代码通过initContentView()方法将BaseActivity中的布局文件添加到了声明的parentLinearLayout中,通过setContentView()方法将子Activity的布局也添加到了parentLinearLayout中,然后又将parentLinearLayout添加到了viewGroup中实现了Activity与布局文件的关联。至此我们完成了第一步,使子Activity可以显示出BaseActivity中的Toolbar布局。 
接下来,我们需要在BaseActivity中对Toolbar进行封装,使其能够更加方便的在子Activity中使用。比如添加toolbar回退键的监听,添加是否显示回退键的方法等。完整的BaseActivity如下:

public abstract class BaseActivity extends AppCompatActivity{
    //the container of this activity layout and sub-activity layout 
    private LinearLayout parentLinearLayout;    private TextView mTvTitle;    private TextView mTvRight;    private Toolbar mToolbar;    @Override
    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);
        initContentView(R.layout.activity_base);

        setContentView(getLayoutId());
        initToolBar();
        setBackIcon();
        init();
    }//  overwrite the function in sub-activity and return the layout id of sub-activity 
 protected abstract int getLayoutId(); private void initContentView(@LayoutRes int layoutResID) {
        ViewGroup viewGroup = (ViewGroup) findViewById(android.R.id.content);
        viewGroup.removeAllViews();
        parentLinearLayout = new LinearLayout(this);
        parentLinearLayout.setOrientation(LinearLayout.VERTICAL);
        viewGroup.addView(parentLinearLayout);        //  add the layout of BaseActivity in parentLinearLayout
        LayoutInflater.from(this).inflate(layoutResID, parentLinearLayout, true);
    }   /**
     * @param layoutResID  the layout id of sub Activity
     */
    @Override
    public void setContentView(@LayoutRes int layoutResID) {        //  added the sub-activity layout id in parentLinearLayout
        LayoutInflater.from(this).inflate(layoutResID, parentLinearLayout, true);

    }private void setBackIcon(){        if (null != getToolbar() && isShowBacking()) {
            getToolbar().setNavigationIcon(R.drawable.icon_back);
            getToolbar().setNavigationOnClickListener((v) -> onBackPressed());
        }
    }    /**
     * @return TextView in center
     */
    public TextView getToolbarTitle() {        return mTvTitle;
    }    /**
     * @return TextView on the right
     */
    public TextView getSubTitle() {        return mTvRight;
    }    /**
     * set Title
     * @param title
     */
    public void setToolBarTitle(CharSequence title) {        if (mTvTitle != null) {
            mTvTitle.setText(title);
        } else {
            getToolbar().setTitle(title);
            setSupportActionBar(getToolbar());
        }
    }    /**
     * the toolbar of this Activity
     * @return support.v7.widget.Toolbar.
     */
    public Toolbar getToolbar() {        return (Toolbar) findViewById(R.id.toolbar);
    }    /**
     * is show back icon,default is none。
     * you can override the function in subclass and return to true show the back icon
     * @return
     */
    protected boolean isShowBacking() {        return true;
    }
}
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

  • 28

  • 29

  • 30

  • 31

  • 32

  • 33

  • 34

  • 35

  • 36

  • 37

  • 38

  • 39

  • 40

  • 41

  • 42

  • 43

  • 44

  • 45

  • 46

  • 47

  • 48

  • 49

  • 50

  • 51

  • 52

  • 53

  • 54

  • 55

  • 56

  • 57

  • 58

  • 59

  • 60

  • 61

  • 62

  • 63

  • 64

  • 65

  • 66

  • 67

  • 68

  • 69

  • 70

  • 71

  • 72

  • 73

  • 74

  • 75

  • 76

  • 77

  • 78

  • 79

  • 80

  • 81

  • 82

  • 83

  • 84

  • 85

  • 86

  • 87

  • 88

  • 89

最后我们可以在子Activity中去使用toolbar了。 
我们让MainActivity继承BaseActivity,并在布局文件中添加一个button,切布局文件中没有添加标题栏,布局文件的代码就不再贴出了。然后 重写isShowBacing()方法,使其返回false,隐藏MainActivity的回退键。 
代码如下:

public class MainActivity extends BaseActivity {
    @BindView(R.id.btn)
    Button mBtn1;    @Override
    protected int getLayoutId() {        return R.layout.activity_main;
    }     @Override
    protected boolean isShowBacking() {        return false;
    }@OnClick({R.id.btn})    public void Onclick(View view){        switch (view.getId()){            case R.id.btn:
                startActivity(new Intent(this,TestActivity.class));                break;
        }
    }
}
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

创建TestActivity并继承BaseActivity,TestActivity的布局文件中不添加任何view。然后在TestActivity中给toolbar设置内容,如下:

public class TestActivity extends BaseActivity {

    @Override
    protected int getLayoutId() {        return R.layout.activity_test;
    }    @Override
    protected void init() {
        getToolbarTitle().setText("中间标题");
        getSubTitle().setText("右边标题");
        Toolbar toolbar = getToolbar();
        toolbar.setLogo(R.mipmap.ic_launcher);
        toolbar.setNavigationIcon(R.drawable.back_white);
    }
}
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

效果如下图所示

0?wx_fmt=gif

0?wx_fmt=jpeg

本网站文章均为原创内容,并可随意转载,但请标明本文链接
如有任何疑问可在文章底部留言。为了防止恶意评论,本博客现已开启留言审核功能。但是博主会在后台第一时间看到您的留言,并会在第一时间对您的留言进行回复!欢迎交流!
本文链接: https://leetcode.jp/baseactivity中封装通用的toolbar/

此条目发表在Android分类目录。将固定链接加入收藏夹。

发表评论

您的电子邮箱地址不会被公开。