android仿QQ優雅的修改App字型大小
阿新 • • 發佈:2019-01-10
最近公司有需求需要在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內使用,不然會報錯
下載地址