1. 程式人生 > >android仿QQ優雅的修改App字型大小

android仿QQ優雅的修改App字型大小

最近公司有需求需要在App裡提供修改應用字型大小的功能,網上查了下資料,感覺都不是和理想,後決定自己實現功能。

實現原理

根據Activity的主題動態修改,在主題中新增自定義的字型大小屬性,滿足不同字型大小的需求,修改時將主題儲存在SharedPreferences裡面。當返回之前的Activity頁面重新顯示的時候,會呼叫onWindowFocusChanged方法,再根據當前的主題是否和SharedPreferences儲存的主題是否相同決定是否recreate當前的Activity,當前的主題通過重寫setTheme方法獲取,廢話不多說,直接上程式碼

package com.xc.theme;

import
android.app.Activity; import android.content.SharedPreferences; import android.support.annotation.StyleRes; import android.support.v7.app.AppCompatActivity; import android.util.Log; /*** * 所有需要跟隨主題改變的類都繼承此基類 **/ public class BaseThemeActivity extends AppCompatActivity { /** * 儲存當前使用的主題ID */
private int mCurrentThemeId; /** * 此方法會在onCreate方法之前被系統執行 * * @param resid */ @Override public void setTheme(@StyleRes int resid) { int savedTheme = ThemeManager.getTheme(this); if (savedTheme > 0 && savedTheme != resid) { resid = savedTheme; } Log.e("print"
,"setTheme before onCreate"); mCurrentThemeId = resid; super.setTheme(resid); } @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { /**不依賴外部呼叫,通過系統回撥函式當從設定頁面返回就會自動呼叫*/ ThemeManager.recreateIfThemeChanged(this, mCurrentThemeId); } } public static class ThemeManager { public static SharedPreferences getThemeSp(Activity context) { return context.getSharedPreferences("themes", MODE_PRIVATE); } public static int getTheme(Activity context) { return getThemeSp(context).getInt("savedTheme", -1); } /** * @param context Activity物件 * @param resid 主題的資源id * @param isRecreate 儲存設定的主題後是否需要重新啟動 */ public static void setTheme(Activity context, @StyleRes final int resid, boolean isRecreate) { if (resid > 0) { getThemeSp(context).edit().putInt("savedTheme", resid).commit(); if (isRecreate) { context.recreate(); } } } public static void recreateIfThemeChanged(Activity context, int mCurrentThemeId) { int savedTheme = getTheme(context); if (savedTheme > 0 && savedTheme != mCurrentThemeId) { context.recreate(); } } } }

setTheme方法會在Activity的onCreate方法之前呼叫,使用者系統設定當前的主題,我們重寫此方法,判斷傳入的resid和我們儲存的savedTheme是否相等,如果不相等,則覆蓋resid設定我們儲存的savedTheme,onWindowFocusChanged的作用是當從字型設定頁面回到前一個頁面的時候呼叫判斷,這樣就和Activity的回撥函式關聯,不用手動的呼叫修改頁面主題,方法中判斷是否和當前的主題相同,不相同的話重新啟動Activity,呼叫recreate方法即可!

自定義字型的大小屬性,style裡的Theme裡新增該屬性

   <!--設定自定義字型屬性-->
    <declare-styleable name="ThemeTextSize">
        <attr name="smallSize" format="dimension" />
        <attr name="normalSize" format="dimension" />
        <attr name="largeSize" format="dimension" />
    </declare-styleable>

在主題中新增自定義的屬性


    <!-- Base application theme. -->
    <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>
        <item name="smallSize">14sp</item>
        <item name="normalSize">16sp</item>
        <item name="largeSize">18sp</item>
        <item name="android:textColor">@android:color/holo_red_light</item>
    </style>

    <!-- Base application theme. -->
    <style name="AppTheme.Smallsize" parent="AppTheme">
        <!-- Customize your theme here. -->
        <item name="smallSize">12sp</item>
        <item name="normalSize">14sp</item>
        <item name="largeSize">16sp</item>
    </style>
    <!-- Base application theme. -->
    <style name="AppTheme.NormalSize" parent="AppTheme">
        <!-- Customize your theme here. -->
        <item name="smallSize">16sp</item>
        <item name="normalSize">18sp</item>
        <item name="largeSize">20sp</item>

    </style>
    <!-- Base application theme. -->
    <style name="AppTheme.LargeSize" parent="AppTheme">
        <!-- Customize your theme here. -->
        <item name="smallSize">20sp</item>
        <item name="normalSize">22sp</item>
        <item name="largeSize">24sp</item>
    </style>

主頁面佈局編寫

<?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"
    android:fitsSystemWindows="true"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:theme="@style/AppTheme.AppBarOverlay"
        app:popupTheme="@style/AppTheme.PopupOverlay"
        app:title="首頁" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="我是主頁面"
        android:textColor="?android:textColor"
        android:textSize="?smallSize" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="我是主頁面"
        android:textColor="?android:textColor"
        android:textSize="?normalSize" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="我是主頁面"
        android:textColor="?android:textColor"
        android:textSize="?largeSize" />

    <Button
        android:id="@+id/btn_next"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="下一頁" />
</LinearLayout>

字型大小通過
android:textSize=”?smallSize”
android:textSize=”?normalSize”
android:textSize=”?largeSize”
實現關聯絡統主題內的字型大小屬性

最後上效果圖

gif可能有點卡,真機上效果很好
設定效果
注意:主題裡面必須有對應的字型屬性值才可以在佈局xml內使用,不然會報錯
下載地址