序言
在做项目的时候,有时候需要一个全局统一的标题栏,保证项目风格的统一,但是如果在每个activity上面都写一遍这个标题栏就很麻烦了,我们经常用的方法就是写个基类Activity,然后当某个Activity需要这个统一的标题栏的时候,继承这个Activity就好了。
实现
1.实现我们需要的标题栏的视图
例如:我们现在需要一个标题栏,左边是Back按钮,返回按钮旁边有文字提示,中间是文字显示,右侧是Home按钮。
我们需要在xml文件中写出这种布局(代码略)
2.创建View加载布局
public class NavBarLayout extends LinearLayout {
private ImageView backNav;
private TextView backName;
private TextView centerName;
private ImageView homeNav;
private INavClickListener listener;
public NavBarLayout(Context context) {
super(context);
init(context);
}
public NavBarLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public NavBarLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
public void setNavClickListener(INavClickListener iNavClickListener) {
this.listener = iNavClickListener;
}
private void init(Context mContext) {
LayoutInflater.from(mContext).inflate(R.layout.layout_top_nav_bar, this);
backNav = findViewById(R.id.image_back);
backName = findViewById(R.id.text_back);
centerName = findViewById(R.id.ext_center);
homeNav = findViewById(R.id.mage_home);
//这是为了增大Back的返回按钮点击区域,将Back按钮和Name区域放在一起
LinearLayout llBack = findViewById(R.id.ll_back_tap);
//默认实现
listener = new INavClickListener() {
@Override
public void backClick(Context context) {
INavClickListener.super.backClick(context);
}
@Override
public void homeClick(Context context) {
INavClickListener.super.homeClick(context);
}
};
//点击返回按钮
llBack.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (listener != null) {
listener.backClick(mContext);
}
}
});
//点击Home按钮
homeNav.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (listener != null) {
listener.homeClick(mContext);
}
}
});
}
/**
* 设置返回按钮图片
*/
public NavBarLayout setNavBackImage(int res) {
backNav.setImageResource(res);
return this;
}
/**
* 设置返回按钮旁边的文字
*/
public NavBarLayout setNavBackName(String text) {
backName.setText(text);
return this;
}
/**
* 设置中间的文字
*/
public NavBarLayout setNavCenterText(String text) {
centerName.setText(text);
return this;
}
/**
* 设置Home按钮图片
*/
public NavBarLayout setNavHomeImage(int res) {
homeNav.setImageResource(res);
return this;
}
/**
* 设置中间文字是否显示
*/
public NavBarLayout setNavCenterIsShow(boolean isShow) {
if (isShow) {
centerName.setVisibility(View.VISIBLE);
} else {
centerName.setVisibility(View.GONE);
}
return this;
}
/**
* 设置Home图案是否显示
*/
public NavBarLayout setNavHomeIsShow(boolean isShow) {
if (isShow) {
homeNav.setVisibility(View.VISIBLE);
} else {
homeNav.setVisibility(View.GONE);
}
return this;
}
public interface INavClickListener {
//默认实现点击返回上一层
default void backClick(Context context) {
Activity activity = (Activity) context;
activity.onBackPressed();
};
//默认实现跳转到某个页面(比如主页面)
default void homeClick(Context context) {
//这里使用了DRouter框架实现页面跳转
DRouter.build("/main").start(context);
};
}
}
这样的话我们的View就实现了,接下来就是在基类里面使用。
3.基类使用
3.1创建基类的xml文件【layout_base】
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_view_base"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#DBE5F1"
android:orientation="vertical">
<com.view.NavBarLayout
android:id="@+id/base_nav"
android:layout_width="match_parent"
android:layout_height="60dp"
android:visibility="visible" />
<FrameLayout
android:id="@+id/ll_child_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
这里我们使用一个上下布局的线性布局,上边是我们的标题栏布局,下面我们使用了一个FrameLayout帧布局,强烈推荐使用这种布局,不容易产生各种莫名其妙的问题。我们以后使用这个FrameLayout加载我们的子类activity的布局。
3.2基类的Activity
public class BaseActivity extends AppCompatActivity {
private NavBarLayout navBarLayout;
@Override
public void setContentView(int layoutResID) {
super.setContentView(R.layout.layout_base); // 设置整个布局为基础布局
Objects.requireNonNull(getSupportActionBar()).hide(); // 隐藏ActionBar/Toolbar
FrameLayout parentView = findViewById(R.id.ll_child_view); // 获取基础布局中的父容器
navBarLayout = findViewById(R.id.base_nav); // 获取基础布局中的导航栏
View childView = LayoutInflater.from(this).inflate(layoutResID, parentView, false); // 根据传入的布局资源ID,生成子视图
parentView.addView(childView); // 将子视图添加到父容器中
}
@Override
public void setContentView(View childView) {
super.setContentView(R.layout.layout_base);
Objects.requireNonNull(getSupportActionBar()).hide();
FrameLayout parentView = findViewById(R.id.ll_child_view);
navBarLayout = findViewById(R.id.base_nav);
parentView.addView(childView);
}
@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
super.setContentView(R.layout.layout_base);
Objects.requireNonNull(getSupportActionBar()).hide();
FrameLayout parentView = findViewById(R.id.ll_child_view);
navBarLayout = findViewById(R.id.base_nav);
parentView.addView(view, params);
}
//是否展示我们的导航栏
protected void showNavBar(boolean isShow) {
if (isShow) {
navBarLayout.setVisibility(View.VISIBLE);
} else {
navBarLayout.setVisibility(View.GONE);
}
}
//给外界提供修改我们导航栏的方法
protected NavBarLayout setNavBar() {
return this.navBarLayout;
}
}
这里面我们可以注意到,我们将这个【setContentView】实现了三次,这是非常有必要的,因为我们不知道将来我们到底使用哪一种方法将子Activity的视图加载进来。
4.使用
我们创建一个activity,然后继承这个基类的activity,这样我们就可以使用了。通过我们的【setNavBar()】方法可以修改我们默认的一些显示文字和进行我们默认设置的按钮的点击跳转设置。