您的位置:首页 > 移动开发

android仿QQ优雅的修改App字体大小

2016-11-13 12:33 267 查看
最近公司有需求需要在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内使用,不然会报错

下载地址
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: