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