TopBar

开发过程中我们经常需要在Activity中使用自定义TopBar,如果每个Activity都在xml添加的TopBar组件,然后再在Activity中设置标题什么的,无疑是非常繁琐的,这个时候封装一个常用的BaseTopBarActivity是非常必要的。

效果及说明

android 简单封装mvp android toolbar封装_xml


如图最左边,通常的一个按钮(返回键),一个标题栏,最右边一个菜单。

菜单栏无需封装,直接在所需的Activity使用Menu就可以。所以直接封装按钮和标题栏即可。

简单封装

修改Style

使用Theme.AppCompat.Light.NoActionBar去掉原有的ActionBar

<resources>
    //使用Theme.AppCompat.Light.NoActionBar去掉原有的ActionBar
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
</resources>

使用,几行代码而已

public class MainActivity extends BaseTopBarActivity {

    @Override
    protected int getContentView() {
        return R.layout.activity_main;
    }

    @Override
    protected void init(Bundle savedInstanceState) {
        setTitle("hello");//修改标题
    }

    //通过getMenuInflater()方法得到MenuInflater对象
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        //如果返回false,创建的菜单无法显示
        return true;
    }

    public boolean onOptionsItemSelected(MenuItem item) {
        //通过调用item.getItemId()来判断菜单项
        switch (item.getItemId()) {
            case R.id.add_item:
                Toast.makeText(this, "You Clicked Add", Toast.LENGTH_SHORT).show();
                break;
            case R.id.remove_item:
                Toast.makeText(this, "You clicked Remove", Toast.LENGTH_SHORT).show();
                break;
            default:
        }
        return true;
    }
}

除去Menu组件所用到的代码,思想上面返回键+标题栏,只需要重写两个方法:
1. getContentView():用来return获取当前Activity的布局文件。
2. init(Bundle savedInstanceState):因为继承的关系,用来代替onCreate(Bundle savedInstanceState),后面详细说明。

封装BaseTopBarActivity

XML

布局很简单,一个ToolpBar和一个FrameLayout就行了,所有的操作都在ToolBar上进行。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.demon.demontest.BaseTopBarActivity">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@color/colorPrimary"
        android:fitsSystemWindows="true"
        app:navigationIcon="?attr/homeAsUpIndicator"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"></android.support.v7.widget.Toolbar>

    <FrameLayout
        android:id="@+id/viewContent"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></FrameLayout>
</LinearLayout>

FrameLayout的作用:
我们封装的思想是写一个BaseTopBarActivity继承AppCompatActivity或者Activity,然后让需要用TopBar的Activity继承BaseTopBarActivity,此处以MainActvity为例。所以BaseTopBarActivity的内容就是一个TopBar+MainActvity。而FrameLayout就是用来转载MainActvity的布局。

BaseTopBarActivity
public abstract class BaseTopBarActivity extends AppCompatActivity {
    @BindView(R.id.toolbar)
    Toolbar toolbar;
    @BindView(R.id.viewContent)
    FrameLayout viewContent;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_base_top_bar);
        ButterKnife.bind(this);

        //初始化设置ToolBar,必须放在toolbar调用的方法之前
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayShowTitleEnabled(false);

        //按钮事件,可以用Toolbar的方法修改按钮Icon,也可以跟设置标题一样写在方法里,重写按钮事件
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();//此处返回
            }
        });

        //将继承 TopBarBaseActivity 的布局解析到 FrameLayout里面
        LayoutInflater.from(this).inflate(getContentView(), viewContent);
        init(savedInstanceState);
    }

    //设置标题
    protected void setTitle(String text) {
        toolbar.setTitle(text);
        toolbar.setTitleTextColor(getResources().getColor(R.color.white));
    }

    //获取继承的布局
    protected abstract int getContentView();

    //代替onCreate初始化,防止重复加载
    protected abstract void init(Bundle savedInstanceState);

}

核心思想:

  1. 使用抽象类的方法,使BaseTopBarActivity可以被继承。
  2. 然后使用抽象方法,使得可以重写,从而修改标题,如果按钮事件需要改变,也可以跟修改标题一样进行重写。
  3. 代码注释写点很详细,就不再多讲。

总结

到这里我们的 TopBarBaseActivity 就封装完了,过程比较简单,重要的是这个封装的思路,其实还有很多我们常用的布局都是可以进行封装的。