ToolBar的封装
在开发app过程中,切换不同的fragment经常需要显示不同的toolbar,为了提高代码的质量和编程的效率,需要对toolbar进行统一的封装;
首先toolbar最常用的习惯的在xml中实现
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#0eb48e">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/search"
android:layout_width="40dp"
android:layout_height="match_parent"
android:gravity="center">
<ImageView
android:layout_gravity="center_vertical"
android:layout_width="@dimen/search_size"
android:layout_height="@dimen/search_size"
android:src="@drawable/search"/>
</LinearLayout>
<LinearLayout
android:id="@+id/sel_city"
android:layout_gravity="center"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="北京"
android:textColor="#fff"
android:textSize="20sp"/>
<ImageView
android:layout_marginLeft="@dimen/title_padding"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/jiantou"/>
</LinearLayout>
<LinearLayout
android:id="@+id/msg"
android:layout_width="40dp"
android:layout_height="match_parent"
android:gravity="center"
android:layout_marginRight="5dp"
android:layout_gravity="right|center_vertical"
>
<ImageView
android:layout_width="@dimen/search_size"
android:layout_height="@dimen/search_size"
android:src="@drawable/msg"/>
</LinearLayout>
</FrameLayout>
</android.support.v7.widget.Toolbar>
<FrameLayout
android:id="@+id/fl_content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="14"/>
</LinearLayout >
当然可以抽取toolbar的代码 用includ代替 但是同样会很鸡肋,所以需要对toolbar进行一个简单的封装;即ToolBarHelper——>ToolBarActivity—–>还有就是extents ToolBarActivity的一些要用到的xxxActivity
下面来看ToolBarHelper(即自定义toolbar)代码
public class ToolBarHelper {
/*上下文,创建view的时候需要用到*/
private Context mContext;
/*base view*/
private FrameLayout mContentView;
/*用户定义的view*/
private View mUserView;
/*toolbar*/
private Toolbar mToolBar;
/*视图构造器*/
private LayoutInflater mInflater;
/*
* 两个属性
* 1、toolbar是否悬浮在窗口之上
* 2、toolbar的高度获取
* */
private static int[] ATTRS = {
R.attr.windowActionBarOverlay,
R.attr.actionBarSize
};
public ToolBarHelper(Context context, int layoutId) {
this.mContext = context;
mInflater = LayoutInflater.from(mContext);
/**初始化整个内容*/
initContentView();
/**初始化用户定义的布局*/
initUserView(layoutId);
/**初始化toolbar*/
initToolBar();
}
private void initContentView() {
mContentView = new FrameLayout(mContext);
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
mContentView.setLayoutParams(params);
}
private void initToolBar() {
/**通过inflater获取toolbar的布局文件*/
View toolbar = mInflater.inflate(R.layout.toolbar, mContentView);
mToolBar = (Toolbar) toolbar.findViewById(R.id.id_tool_bar);
}
private void initUserView(int id) {
mUserView = mInflater.inflate(id, null);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
TypedArray typedArray = mContext.getTheme().obtainStyledAttributes(ATTRS);
/**获取主题中定义的悬浮标志*/
boolean overly = typedArray.getBoolean(0, false);
/**获取主题中定义的toolbar的高度*/
int toolBarSize = (int) typedArray.getDimension(1,(int) mContext.getResources().getDimension(R.dimen.abc_action_bar_default_height_material));
typedArray.recycle();
/**如果是悬浮状态,则不需要设置间距*/
params.topMargin = overly ? 0 : toolBarSize;
mContentView.addView(mUserView, params);
}
public FrameLayout getContentView() {
return mContentView;
}
public Toolbar getToolBar() {
return mToolBar;
}
}
在toolbarHelper中通过findViewByID初始化toolbar及其父布局FramLayout,在initUserView对其高度进行了限制,保证之后服用时候高度一致
下面来看ToolBarActivity的代码(相当于之后所有activity的base基类):
public abstract class ToolBarActivity extends AppCompatActivity {
private ToolBarHelper mToolBarHelper ;
public Toolbar toolbar ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void setContentView(int layoutResID) {
mToolBarHelper = new ToolBarHelper(this,layoutResID) ;
toolbar = mToolBarHelper.getToolBar() ;
setContentView(mToolBarHelper.getContentView());
/*把 toolbar 设置到Activity 中*/
setSupportActionBar(toolbar);
/*自定义的一些操作*/
onCreateCustomToolBar(toolbar) ;
}
public void onCreateCustomToolBar(Toolbar toolbar){
toolbar.setContentInsetsRelative(0,0);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home){
finish();
return true ;
}
return super.onOptionsItemSelected(item);
}
}
在ToolBarActivity中就是 从toolBarHelper中获取toolbar对象然后将它加入到activity布局中,当然要注意到最关键的一个方法是onCreateCustomToolBar(toolbar),这个方法是用来被子类activity继承实现不同activity,显示不同的toolbar的关键代码
在这里自定义两个activity(MainActivity 和MainActivity1),废话不多说,先直接来上代码;
Mainactivity:
package toolbar.toolbar;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends ToolBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public void onCreateCustomToolBar(Toolbar toolbar) {
super.onCreateCustomToolBar(toolbar);
toolbar.showOverflowMenu() ;
getLayoutInflater().inflate(R.layout.toobar_button, toolbar) ;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
MenuItem itemCompat = menu.findItem(R.id.action_search) ;
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
startActivity(new Intent(this,MainActivity1.class));
return true;
}
return super.onOptionsItemSelected(item);
}
}
MainActivity1
package toolbar.toolbar;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
/**
* Created by houruixiang on 2017/5/19.
*/
public class MainActivity1 extends ToolBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main1);
}
@Override
public void onCreateCustomToolBar(Toolbar toolbar) {
super.onCreateCustomToolBar(toolbar);
toolbar.showOverflowMenu() ;
View view = getLayoutInflater().inflate(R.layout.toobar_button, toolbar);
((TextView)(view.findViewById(R.id.tv))).setText("my_toolbar");
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
大家可以看到在以后的activity中,布局中根本不需要直接出现toolbar,只需要在onCreateCustomToolBar(Toolbar toolbar),复用同一个toolbar布局R.layout.toobar_button,如果想修改主题之类,只需要获取id重新set即可,是不是较之前来说方便许多;
当然以上是讲的activity,如果是fragment,相信举一反三,同样ok