这边分享一个功能需求,全局改变字体大小。当下的情景比较蛋疼…一个祖传的项目,需要在半路添加这个需求,各种字体大小已经写明在xml里面了,dp,sp,甚至xp不等。当时内心是拒绝的,但是由于用户反馈实在要做,而且app面向的用户为老年用户居多,还是决定踩坑了。这里也善意提醒大家,凡事留一线,日后好给自己留活路。所以,我进入了漫长的百度或者是google…
一. 正确的姿势(我认为)
参考https://blog.csdn.net/mrwangxsyz/article/details/48767555
首先想到的就是通过style设置字体的自定义属性,重启当前应用,通过BaseActivity修改属性标识符去控制当前字体的大小,当前页面需要手动设置,貌似都需要,然后要重启之前的页面。奈何我这个项目已经过半,在xml中基本是写死的,比较绝望当时,原本想硬着头皮继续下去的….
参考思路链接:
二. 勉强将就的姿势(成功瞒过产品经理,并且比ios还改的快)
看到网上有一种方式就是字体设置一般是sp,一开始区分dp的时候就隐约记得有一个缩放系数,那么我们不妨从这里入手,查看下源代码发现是这个scaledDesity
那么我们只需要改变这个参数的大小就可以了,顿时看到了希望
1.思路,首先需要知道的是要改变scaledDesity
//重写字体缩放比例 api<25
@Override
public Resources getResources() {
Resources res =super.getResources();
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N) {
Configuration config = res.getConfiguration();
config.fontScale= MyApplication.getMyInstance().getFontScale();//1 设置正常字体大小的倍数
res.updateConfiguration(config,res.getDisplayMetrics());
}
return res;
}
这里可以看到在25版本以后的api抛弃了这个方法
/**
* Store the newly updated configuration.
*
* @deprecated See {@link android.content.Context#createConfigurationContext(Configuration)}.
*/
@Deprecated
public void updateConfiguration(Configuration config, DisplayMetrics metrics) {
updateConfiguration(config, metrics, null);
}
那么使用这个方法createConfigurationContext
//重写字体缩放比例 api>25
@Override
protected void attachBaseContext(Context newBase) {
if(Build.VERSION.SDK_INT>Build.VERSION_CODES.N){
final Resources res = newBase.getResources();
final Configuration config = res.getConfiguration();
config.fontScale=MyApplication.getMyInstance().getFontScale();//1 设置正常字体大小的倍数
final Context newContext = newBase.createConfigurationContext(config);
super.attachBaseContext(newContext);
}else{
super.attachBaseContext(newBase);
}
}
2.正常情况下需要通知下发关闭前面的设置页面,然后重启主页面。这里使用EventBus或者RxBus通知会方便一些
这里使用了RxBus
2.1.RxBus的使用
添加依赖
compile 'io.reactivex.rxjava2:rxjava:2.0.5'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
RxBus代码:
package com.demo.textsizechange;
import android.support.annotation.NonNull;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import io.reactivex.Observable;
import io.reactivex.subjects.PublishSubject;
import io.reactivex.subjects.Subject;
/**
* Created by RJS on 2016/7/18.
*/
public class RxBus {
private ConcurrentHashMap
3.需要重启页面
// this.recreate();
Intent intent = getIntent();
overridePendingTransition(0, 0);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
finish();
overridePendingTransition(0, 0);
startActivity(intent);
4.那个滑动或者点击滑块需要的控件FontSliderBar
可以参考这篇文章,我这边应用了这个库,稍微做了下修改https://blog.csdn.net/llew2011/article/details/51668407
5.ok基本上比较清晰了,上代码
BaseActivity.java
package com.demo.textsizechange;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
/**
* Created by zsj on 2016/8/4.
*/
public abstract class BaseActivity extends AppCompatActivity {
public Observable observable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
observable = RxBus.getInstance().register(this.getClass().getSimpleName(), MessageSocket.class);
observable.observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer() {
@Override
public void accept(MessageSocket message) throws Exception {
rxBusCall(message);
}
});
}
public void rxBusCall(MessageSocket message) {
}
public int getColorById(int resId) {
return ContextCompat.getColor(this, resId);
}
public void goActivity(Class> activity) {
Intent intent = new Intent();
intent.setClass(getApplicationContext(), activity);
startActivity(intent);
}
@Override
protected void onDestroy() {
super.onDestroy();
RxBus.getInstance().unregister(this.getClass().getSimpleName(), observable);
}
//重写字体缩放比例 api<25
@Override
public Resources getResources() {
Resources res =super.getResources();
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N) {
Configuration config = res.getConfiguration();
config.fontScale= MyApplication.getMyInstance().getFontScale();//1 设置正常字体大小的倍数
res.updateConfiguration(config,res.getDisplayMetrics());
}
return res;
}
//重写字体缩放比例 api>25
@Override
protected void attachBaseContext(Context newBase) {
if(Build.VERSION.SDK_INT>Build.VERSION_CODES.N){
final Resources res = newBase.getResources();
final Configuration config = res.getConfiguration();
config.fontScale=MyApplication.getMyInstance().getFontScale();//1 设置正常字体大小的倍数
final Context newContext = newBase.createConfigurationContext(config);
super.attachBaseContext(newContext);
}else{
super.attachBaseContext(newBase);
}
}
}
使用TextSizeShowActivity
package com.demo.textsizechange;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.view.KeyEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import fontsliderbar.FontSliderBar;
/**
* Created by zsj on 2017/9/11.
* 字体设置展示
*/
public class TextSizeShowActivity extends BaseActivity {
@BindView(R.id.fontSliderBar)
FontSliderBar fontSliderBar;
@BindView(R.id.tv_chatcontent1)
TextView tvContent1;
@BindView(R.id.tv_chatcontent)
TextView tvContent2;
@BindView(R.id.tv_chatcontent3)
TextView tvContent3;
@BindView(R.id.iv_back)
ImageView ivBack;
@BindView(R.id.iv_userhead)
ImageView ivUserhead;
private float textsize1, textsize2, textsize3;
private float textSizef;//缩放比例
private int currentIndex;
private boolean isClickable = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_textsizeshow);
ButterKnife.bind(this);
initData();
}
private void initData() {
currentIndex = MyApplication.getMyInstance().getPreferencesHelper().getValueInt("currentIndex", 1);
textSizef = 1 + currentIndex * 0.1f;
textsize1 = tvContent1.getTextSize() / textSizef;
textsize2 = tvContent2.getTextSize() / textSizef;
textsize3 = tvContent3.getTextSize() / textSizef;
fontSliderBar.setTickCount(6).setTickHeight(DisplayUtils.convertDip2Px(TextSizeShowActivity.this, 15)).setBarColor(Color.GRAY)
.setTextColor(Color.BLACK).setTextPadding(DisplayUtils.convertDip2Px(TextSizeShowActivity.this, 10)).setTextSize(DisplayUtils.convertDip2Px(TextSizeShowActivity.this, 14))
.setThumbRadius(DisplayUtils.convertDip2Px(TextSizeShowActivity.this, 10)).setThumbColorNormal(Color.GRAY).setThumbColorPressed(Color.GRAY)
.setOnSliderBarChangeListener(new FontSliderBar.OnSliderBarChangeListener() {
@Override
public void onIndexChanged(FontSliderBar rangeBar, int index) {
if(index>5){
return;
}
index = index - 1;
float textSizef = 1 + index * 0.1f;
setTextSize(textSizef);
}
}).setThumbIndex(currentIndex).withAnimation(false).applay();
ivBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (fontSliderBar.getCurrentIndex() != currentIndex) {
if (isClickable) {
isClickable = false;
refresh();
}
} else {
finish();
}
}
});
}
private void setTextSize(float textSize) {
//改变当前页面的字体大小
tvContent1.setTextSize(DisplayUtils.px2sp(TextSizeShowActivity.this, textsize1 * textSize));
tvContent2.setTextSize(DisplayUtils.px2sp(TextSizeShowActivity.this, textsize2 * textSize));
tvContent3.setTextSize(DisplayUtils.px2sp(TextSizeShowActivity.this, textsize3 * textSize));
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (currentIndex != fontSliderBar.getCurrentIndex()) {
if (isClickable) {
isClickable = false;
refresh();
}
} else {
finish();
}
return true;
}
return super.onKeyDown(keyCode, event);
}
private void refresh() {
//存储标尺的下标
MyApplication.getMyInstance().getPreferencesHelper().setValue("currentIndex", fontSliderBar.getCurrentIndex());
//通知主页面重启
RxBus.getInstance().post(MainActivity.class.getSimpleName(), new MessageSocket(99, null, null, null));
//重启mainActivity
RxBus.getInstance().post(MainActivity.class.getSimpleName(), new MessageSocket(99, null, null, null));
// showMyDialog();
//2s后关闭 延迟执行任务 重启完主页
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// hideMyDialog();
finish();
}
}, 2000);
}
}
源码地址:https://download.csdn.net/download/z_zt_t/10505492
https://github.com/TrebleZ/TextSizeChange
三.总结
不将就一个个修改,那么久沉下心来分析,然后总结下,避免下次继续踩坑。