注册

我的Android开发之旅(一):BaseActivity的浅入之简单封装 Toolbar

为什么要写BaseAcivity


我们都知道在做Android应用开发的时候都需要创建一个Activity,但很多时候我们的程序有多个界面并且每个界面都有相似的内容(例如:Toolbar、DrawerLayout)和后台的操作有共同的方法,这个时候我们写一个BaseActivity作为每一个Activity的基类,统一管理程序中的每个Activity。


一行代码实现 Toolbar 效果


activity_main.xml 的代码


<?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"
tools:context=".MainActivity"
android:gravity="center"
android:background="@android:color/holo_blue_light">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我是MainActivity的界面"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</LinearLayout>

MainAcitvity.java 的代码


public class MainActivity extends BaseActivity {

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

在这里插入图片描述
在上面的 activity_main.xml 中可以看出,父布局设置了背景颜色和里面只有一个TextView,并没图中的Toolbar。那到底是为什么呢?其实细心观察的小伙伴们会发现,怎么MainActivity中的代码和平常不一样呢?onCreate()方法呢?别急,我们重头开始!


“少啰嗦,先看东西”




  • 创建 BaseActivity


    在项目创建后,我们可以看到AndroidStudio自动帮我们生成了MainActivity.java和activity_main.xml文件,然后我们再创建一个新的Activity,命名为BaseActivity。

    在这里插入图片描述




  • 修改 activity_base.xml 文件


    接着打开activity_base.xml文件,把父布局的ConstraintLayout换成垂直的LinearLayout(其实也可以不换的,主要是我喜欢用LinearLayout),并在里面添加两个元素Toolbar和FrameLayout。



    注意:由于Toolbar代替 ActionBar,所以先把 ActionBar 去掉,我们通过设置 Application 的 theme 来隐藏,这样项目中所有的界面的 ActionBar 就都隐藏了。





<?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"
tools:context=".BaseActivity"
android:orientation="vertical">

<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

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

</FrameLayout>

</LinearLayout>


  • 修改 BaseActivity.java 文件


    接下来打开 BaseActivity.java 文件,让 BaseActivity 继承 AppCompatActivity ,修改代码如下



    注意:protected abstract int getContentView(); 是一个抽象方法,所以我们要将 BaseActivity 修改成抽象类。为什么要修改成抽象类呢?原因很简单,因为一个类里是不允许有一个抽象方法的,如要有抽象方法,那这个类就必须是抽象类。那可能你又会问,为什么要用抽象方法呢?(你是十万个为什么吗?哪来的那么多为什么)因为我们想让其他 Activity 的界面显示到 BaseActivity 中,那这个方法是必须要实现的,如果设置成普通的方法的话,我们很有可能在写代码的时候忘记了调用了这个方法,导致界面不显示。所以我们得用抽象方法,这样每个 Activity 继承这个 BaseActivity 的时候就必须覆写 getContentView() 这个方法。





public abstract class BaseActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
initView();
}

private void initView() {
// 绑定控件
Toolbar toolbar = findViewById(R.id.toolbar);
FrameLayout container = findViewById(R.id.container);
// 初始化设置Toolbar
toolbar.setTitle("我是BaseActivity的Toolbar");
setSupportActionBar(toolbar);
// 将继承了BaseActivity的布局文件解析到 container 中,这样 BaseActivity 就能显示 MainActivity 的布局文件了
LayoutInflater.from(this).inflate(getContentView(), container);
}

/**
* 获取要显示内容的布局文件的资源id
*
* @return 显示的内容界面的资源id
*/
protected abstract int getContentView();

}

  • 修改 activity_main.xml 文件
    打开 activity_main.xml 文件,然后我们将父布局的背景颜色修改一下,方便我们辨别到底是 MainActivity 的布局文件还是 BaseActivity 的布局文件。再添加添加一个 TextView ,原因也是和修改背景颜色是一样的。

<?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"
tools:context=".MainActivity"
android:gravity="center"
android:background="@android:color/holo_blue_light">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我是MainActivity的界面"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</LinearLayout>

  • 修改 MainActivity.java 文件
    让 MainActivity 继承 BaseActivity 并覆写 getContentView() 方法,然后删除onCreate()方法。通过 getContentView() 方法返回当前的布局资源ID给 BaseActivity,让 BaseActivity 加载布局文件。

public class MainActivity extends BaseActivity {

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


  • 运行项目


    现在你运行一下项目,我们并没有在 MainActivity 的布局中添加 ToolBar,但是运行出来的效果是 Toolbar 已经存在了。

    在这里插入图片描述
    现在就能做到用一行代码实现 Toolbar 的效果。那你现在可能就会有疑问,如果我像对 Toolbar 修改标题和添加按钮呢?其实也简单,我们继续往下看。




  • 修改标题
    我们在 BaseActivity 中再添加一个抽象方法,并在初始化 Toolbar 那一处调用我们写的这个抽象方法。




public abstract class BaseActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
initView();
}

private void initView() {
// 绑定控件
Toolbar toolbar = findViewById(R.id.toolbar);
FrameLayout container = findViewById(R.id.container);
// 初始化设置Toolbar
toolbar.setTitle(setTitle());
setSupportActionBar(toolbar);
// 将继承了BaseActivity的布局文件解析到 container 中,这样 BaseActivity 就能显示 MainActivity 的布局文件了
LayoutInflater.from(this).inflate(getContentView(), container);
}

/**
* 获取要显示内容的布局文件的资源id
*
* @return 显示的内容界面的资源id
*/
protected abstract int getContentView();

/**
* 设置标题
*
* @return 要显示的标题名称
*/
protected abstract String setTitle();

}

  • 修改 MainActivity.java
    我们还是像刚才一样覆写 setTitle() 方法,并在返回值输入我们想要显示的标题

public class MainActivity extends BaseActivity {

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

@Override
protected String setTitle() {
return "我是MainActivity的标题";
}
}

这个时候再运行以下你的程序就会出现你设置的标题了。

在这里插入图片描述那么现在你可能又会问了,如果我想对 Toolbar 添加一个返回按钮,并能对他进行操作应该怎么办?(我不想写了,你也别问了!)其实很简单,在 BaseActivity 里自定义一个接口,在子类中设置这个接口的实例就行。




  • 显示返回按钮
    我们先给 Toolbar 显示返回按钮,通过 getSupportActionBar() 得到 ActionBar 的实例,再调用 ActionBar 的 setDisplayHomeAsUpEnabled(true) 方法让返回按钮显示出来。



    Toolbar 最左侧的按钮是叫做HomeAsUp,默认是隐藏的,并且它的图标是一个返回箭头。还有一种 setNavigationcon() 方法也能设置图标,具体可以查找 Toolbar 的文档说明





private void initView() {
// 绑定控件
Toolbar toolbar = findViewById(R.id.toolbar);
FrameLayout container = findViewById(R.id.container);
// 初始化设置Toolbar
toolbar.setTitle(setTitle());
setSupportActionBar(toolbar);
// 将继承了BaseActivity的布局文件解析到 container 中,这样 BaseActivity 就能显示 MainActivity 的布局文件了
LayoutInflater.from(this).inflate(getContentView(), container);
// 显示返回按钮
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
// 初始化
init();
}


  • 自己定义一个接口并声明
    这里我就用截图显示代码片段

    在这里插入图片描述




  • 设置监听事件
    打开 MainActivity.java 文件,覆写 init() 方法,并调用父类的 setBackOnClickListener() 方法。



    这里我用了 lambda 表达式,这是 java 8 才支持的,默认项目是不支持的,你在 build.gradle 中需要声明一下。





	@Override
protected void init() {
setBackOnClickListener(() ->
Toast.makeText(this, "点击了一下返回按钮", Toast.LENGTH_SHORT).show()
);
}

  • 运行app
    在这里插入图片描述

最后


相信你对 BaseActivity 有了一些简单的了解了,具体如何使用还是得看你的项目,不是项目里就一定要写 BaseActivity 和所有 Activity 都要继承 BaseActivity ,我只是将我所理解的 BaseActivity 和大家分享一下。可能你看完了这一篇文章发现还是没能理解,在这里我想说声抱歉,可能有些地方讲的不够通俗易懂或是讲解有误,还请您多多指教,我会虚心接受并及时改正(就算是讲错了我也不会改)。



Demo的Github地址:
github.com/lmx0206/Bas…
Demo的Gitee地址:
gitee.com/Leungmx/Bas…


作者:梁大侠
链接:https://juejin.cn/post/6844904146659704846
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册