個人Android開發之旅(一):BaseActivity的淺入之簡單封裝 Toolbar

爲何要寫BaseAcivity

咱們都知道在作Android應用開發的時候都須要建立一個Activity,但不少時候咱們的程序有多個界面而且每一個界面都有類似的內容(例如:Toolbar、DrawerLayout)和後臺的操做有共同的方法,這個時候咱們寫一個BaseActivity做爲每個Activity的基類,統一管理程序中的每一個Activity。php

一行代碼實現 Toolbar 效果

activity_main.xml 的代碼java

<?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 的代碼android

public class MainActivity extends BaseActivity {

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

複製代碼

在這裏插入圖片描述
在上面的 activity_main.xml 中能夠看出,父佈局設置了背景顏色和裏面只有一個TextView,並沒圖中的Toolbar。那究竟是爲何呢?其實細心觀察的小夥伴們會發現,怎麼MainActivity中的代碼和日常不同呢?onCreate()方法呢?別急,咱們重頭開始!

「少囉嗦,先看東西」

  • 建立 BaseActivitygit

    在項目建立後,咱們能夠看到AndroidStudio自動幫咱們生成了MainActivity.java和activity_main.xml文件,而後咱們再建立一個新的Activity,命名爲BaseActivity。github

    在這裏插入圖片描述

  • 修改 activity_base.xml 文件app

    接着打開activity_base.xml文件,把父佈局的ConstraintLayout換成垂直的LinearLayout(其實也能夠不換的,主要是我喜歡用LinearLayout),並在裏面添加兩個元素Toolbar和FrameLayout。ide

    注意:因爲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 文件gradle

    接下來打開 BaseActivity.java 文件,讓 BaseActivity 繼承 AppCompatActivity ,修改代碼以下ui

    注意: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…

相關文章
相關標籤/搜索