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内使用,不然会报错
下载地址

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值