image

目录

一、前言

二、效果预览

三、实现步骤

1、自定义字体调整控件

2、滑动按钮改变当前页面预览字体大小

3、返回时,保存放大倍数并重启应用

4、初始化应用时配置字体放大倍数。

四、Demo地址

五、内容推荐

一、前言

最近项目添加了一项调整应用字体大小功能,做完后空闲之余总结一下。本功能仿照微信应用“设置” - “通用” - “字体大小”功能,又有一点区别。据我所知,常见改变全局字体大小方法有两种(若有更好的方案可以留言,互相学习),我把这两种分为可控和不可控,为什么这么分呢,当然不是为了方便记忆。那么简单说下两者方式的实现过程:

1、不可控:通过重写Actiivity的getResources()方法更新应用的字体倍数来调整全局字体大小

优点:实现简单

缺点:不可控制(所有字体放大倍数都是一致),无法跨进程(项目中另一个进程的字体不会改变,需要重新配置),只对sp字体单位有效果。....

2、可控:通过setTheme()方法,一开始就初始化设置不同风格的字体样式来更改全局字体大小。

优点:随意调节任意位置的字体大小

缺点:实现麻烦

而本文正式采用了第一种方案,主要是中途添加该功能,时间也不充裕,抽取字体大小又太过耗时。

微信字体大小个人猜测使用第二种方案,后者是更好的实现方式也不一定。

好了,扯得有点多。我要开始真正的表演了 ... 掌声呢 鲜花呢 .....................人呢

image

二、效果预览

image

三、实现步骤

1、自定义字体调整控件

网上找了一个相似的控件并加以完善,功能相对简单,就不做介绍了。

import android.content.Context;

import android.content.res.TypedArray;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.Point;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.view.View;

import java.util.ArrayList;

import java.util.List;

import blcs.lwb.lwbtool.R;

import blcs.lwb.lwbtool.utils.DensityUtils;

/**

* TODO 仿微信字体大小调整

* 自定义属性:

* lineWidth 线条粗细

* lineColor 线条颜色

* totalCount 线条格数

* circleColor 球型颜色

* circleRadius 球型颜色半径

* textFontColor 文字颜色

* smallSize 小“A” 字体大小

* standerSize “标准” 字体大小

* bigSize 大“A” 字体大小

* defaultPosition 默认位置

*/

public class FontSizeView extends View {

private int defaultLineColor = Color.rgb(33, 33, 33);

private int defaultLineWidth;

private int defaultMax = 5;

private int defaultCircleColor = Color.WHITE;

private int defaultCircleRadius;

// 当前所在位置

private int currentProgress;

// 默认位置

private int defaultPosition = 1;

// 一共有多少格

private int max = 7;

// 线条颜色

private int lineColor = Color.BLACK;

// 线条粗细

private int lineWidth;

//字体颜色

private int textColor = Color.BLACK;

//字体大小

private int smallSize = 14;

private int standerSize = 16;

private int bigSize = 28;

// 圆半径

private int circleRadius;

private int circleColor = Color.WHITE;

// 一段的宽度,根据总宽度和总格数计算得来

private int itemWidth;

// 控件的宽高

private int height;

private int width;

// 画笔

private Paint mLinePaint;

private Paint mTextPaint;

private Paint mText1Paint;

private Paint mText2Paint;

private Paint mCirclePaint;

// 滑动过程中x坐标

private float currentX = 0;

// 有效数据点

private List points = new ArrayList<>();

private float circleY;

private float textScaleX;

private float text1ScaleX;

private float text2ScaleX;

public FontSizeView(Context context) {

this(context, null);

}

public FontSizeView(Context context, AttributeSet attrs) {

super(context, attrs);

init(context, attrs);

}

private void init(Context context, AttributeSet attrs) {

// initDefault

defaultLineWidth = DensityUtils.dp2px(context, 2);

defaultCircleRadius = DensityUtils.dp2px(context, 35);

lineWidth = DensityUtils.dp2px(context, 1);

TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FontSizeView);

final int N = typedArray.getIndexCount();

for (int i = 0; i < N; i++) {

initCustomAttr(typedArray.getIndex(i), typedArray);

}

typedArray.recycle();

// 初始化画笔

mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);

mLinePaint.setColor(lineColor);

mLinePaint.setStyle(Paint.Style.FILL_AND_STROKE);

mLinePaint.setStrokeWidth(lineWidth);

//文字画笔

mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

mTextPaint.setColor(textColor);

mTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);

// mTextPaint.setStrokeWidth(DensityUtils.dp2px(context, 1));

mTextPaint.setTextSize(DensityUtils.sp2px(context, smallSize));

textScaleX = mTextPaint.measureText("A");

//文字画笔

mText1Paint = new Paint(Paint.ANTI_ALIAS_FLAG);

mText1Paint.setColor(textColor);

mText1Paint.setStyle(Paint.Style.FILL_AND_STROKE);

mText1Paint.setTextSize(DensityUtils.sp2px(context, bigSize));

text1ScaleX = mText1Paint.measureText("A");

//文字画笔

mText2Paint = new Paint(Paint.ANTI_ALIAS_FLAG);

mText2Paint.setColor(textColor);

mText2Paint.setStyle(Paint.Style.FILL_AND_STROKE);

mText2Paint.setTextSize(DensityUtils.sp2px(context, standerSize));

text2ScaleX = mText2Paint.measureText("标准");

mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);

mCirclePaint.setColor(circleColor);

mCirclePaint.setStyle(Paint.Style.FILL);

// 设置阴影效果

setLayerType(LAYER_TYPE_SOFTWARE, null);

mCirclePaint.setShadowLayer(2, 0, 0, Color.rgb(33, 33, 33));

}

private void initCustomAttr(int attr, TypedArray typedArray) {

if (attr == R.styleable.FontSizeView_lineColor) {

lineColor = typedArray.getColor(attr, defaultLineColor);

} else if (attr == R.styleable.FontSizeView_circleColor) {

circleColor = typedArray.getColor(attr, defaultCircleColor);

} else if (attr == R.styleable.FontSizeView_lineWidth) {

lineWidth = typedArray.getDimensionPixelSize(attr, defaultLineWidth);

} else if (attr == R.styleable.FontSizeView_circleRadius) {

circleRadius = typedArray.getDimensionPixelSize(attr, defaultCircleRadius);

} else if (attr == R.styleable.FontSizeView_totalCount) {

max = typedArray.getInteger(attr, defaultMax);

} else if (attr == R.styleable.FontSizeView_textFontColor) {

textColor = typedArray.getColor(attr, textColor);

} else if (attr == R.styleable.FontSizeView_smallSize) {

smallSize = typedArray.getInteger(attr, smallSize);

} else if (attr == R.styleable.FontSizeView_standerSize) {

standerSize = typedArray.getInteger(attr, standerSize);

} else if (attr == R.styleable.FontSizeView_bigSize) {

bigSize = typedArray.getInteger(attr, bigSize);

}else if (attr == R.styleable.FontSizeView_defaultPosition) {

defaultPosition = typedArray.getInteger(attr, defaultPosition);

}

}

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh);

height = h;

width = w;

circleY = height / 2;

// 横线宽度是总宽度-2个圆的半径

itemWidth = (w - 2 * circleRadius) / max;

// 把可点击点保存起来

for (int i = 0; i <= max; i++) {

points.add(new Point(circleRadius + i * itemWidth, height / 2));

}

//初始刻度

currentX = points.get(defaultPosition).x;

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

//画字

canvas.drawText("A", points.get(0).x - textScaleX / 2, height / 2 - 50, mTextPaint);

//画字

canvas.drawText("标准", points.get(1).x - text2ScaleX / 2, height / 2 - 50, mText2Paint);

//画字

canvas.drawText("A", points.get(points.size() - 1).x - text1ScaleX / 2, height / 2 - 50, mText1Paint);

// 先画中间的横线

canvas.drawLine(points.get(0).x, height / 2, points.get(points.size() - 1).x, height / 2, mLinePaint);

// 绘制刻度

for (Point point : points) {

canvas.drawLine(point.x + 1, height / 2 - 20, point.x + 1, height / 2 + 20, mLinePaint);

}

// 画圆

if (currentX < circleRadius) {

currentX = circleRadius;

}

if (currentX > width - circleRadius) {

currentX = width - circleRadius;

}

// 实体圆

canvas.drawCircle(currentX + 1, circleY, circleRadius, mCirclePaint);

}

@Override

public boolean onTouchEvent(MotionEvent event) {

currentX = event.getX();

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

invalidate();

break;

case MotionEvent.ACTION_MOVE:

invalidate();

break;

case MotionEvent.ACTION_UP:

//回到最近的一个刻度点

Point targetPoint = getNearestPoint(currentX);

if (targetPoint != null) {

// 最终

currentX = points.get(currentProgress).x;

invalidate();

}

if (onChangeCallbackListener != null) {

onChangeCallbackListener.onChangeListener(currentProgress);

}

break;

}

return true;

}

/**

* 获取最近的刻度

*/

private Point getNearestPoint(float x) {

for (int i = 0; i < points.size(); i++) {

Point point = points.get(i);

if (Math.abs(point.x - x) < itemWidth / 2) {

currentProgress = i;

return point;

}

}

return null;

}

public void setChangeCallbackListener(OnChangeCallbackListener listener) {

this.onChangeCallbackListener = listener;

}

private OnChangeCallbackListener onChangeCallbackListener;

public interface OnChangeCallbackListener {

void onChangeListener(int position);

}

public void setDefaultPosition(int position){

defaultPosition=position;

if (onChangeCallbackListener != null) {

onChangeCallbackListener.onChangeListener(defaultPosition);

}

invalidate();

}

}

image.gif

xml使用方式:

android:id="@+id/fsv_font_size"

android:layout_width="wrap_content"

android:layout_height="120dp"

android:layout_marginLeft="@dimen/space_line2"

android:layout_marginRight="@dimen/space_line2"

android:background="@color/white"

app:circleRadius="11dp"

app:lineColor="@color/round_corner_progress_bar_progress_default"

app:standerSize="16" />

image.gif

2、滑动按钮改变当前页面预览字体大小

//备注

14sp

16sp

18sp

20sp

22sp

24sp

26sp

28sp

image.gif

//滑动返回监听

fsvFontSize.setChangeCallbackListener(new FontSizeView.OnChangeCallbackListener() {

@Override

public void onChangeListener(int position) {

int dimension = getResources().getDimensionPixelSize(R.dimen.sp_stander);

//根据position 获取字体倍数

fontSizeScale = (float) (0.875 + 0.125 * position);

//放大后的sp单位

double v = fontSizeScale * (int) DensityUtils.px2sp(FontSizeActivity.this, dimension);

//改变当前页面大小

changeTextSize((int) v);

}

});

image.gif

/**

* 改变textsize 大小

*/

private void changeTextSize(int dimension) {

tv_font_size1.setTextSize(dimension);

tv_font_size2.setTextSize(dimension);

tv_font_size3.setTextSize(dimension);

}

image.gif

3、返回时,保存放大倍数并重启应用

public void onClick(View view) {

SPUtils.put(FontSizeActivity.this,Constants.SP_FontScale,fontSizeScale);

//重启应用

AppManager.getAppManager().finishAllActivity();

IntentUtils.toActivity(FontSizeActivity.this, MainActivity.class,true);

}

image.gif

4、初始化应用时配置字体放大倍数。

改变全局大小的关键

res.updateConfiguration(config,res.getDisplayMetrics())

//fontSizeScale = (float) SPUtils.get(this, Constants.SP_FontScale, 0.0f);

@Override

public Resources getResources() {

Resources res =super.getResources();

Configuration config = res.getConfiguration();

if(fontSizeScale>0.5){//防止第一次获取SP时得到默认值0

config.fontScale= fontSizeScale;//设置正常字体大小的倍数

}

res.updateConfiguration(config,res.getDisplayMetrics());

return res;

}

image.gif

就是这么简单。。细节我就不写了 ,贴出来代码太长。看着累 ,需要的大家可以去看我项目

image

四、Demo地址

五、内容推荐

如果你觉得我写的不错或者对您有所帮助的话

不妨顶一个【微笑】,别忘了点赞、收藏、加关注哈

您的每个举动都是对我莫大的支持

image

Android全局修改字体大小,Android 仿微信全局字体大小调整相关推荐

  1. Android 天气APP(十三)仿微信弹窗(右上角加号点击弹窗效果)、自定义背景图片、UI优化调整

    上一篇:Android 天气APP(十二)空气质量.UI优化调整 天气预报详情,逐小时预报详情 新版------------------- 一.适配器点击监听 二.页面实现 三.天气预报详情弹窗 四. ...

  2. Android ActionBar应用实战,高仿微信主界面的设计

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/26365683 经过前面两篇文章的学习,我想大家对ActionBar都已经有一个相对 ...

  3. android 调出键盘表情_android高仿微信表情输入与键盘输入代码(详细实现分析)

    表情与键盘的切换输入大部分IM都会需要到,之前自己实现了一个,还是存在些缺陷,比如说键盘与表情切换时出现跳闪问题,这个困扰了我些时间,不过所幸在Github(其代码整体结构很不错)并且在论坛上找些解决 ...

  4. 【Android App】实战项目之仿微信的私信和群聊App(附源码和演示视频 超详细必看)

    需要全部代码请点赞关注收藏后评论区留言私信~~~ 手机最开始用于通话,后来增加了短信功能,初步满足了人与人之间的沟通需求.然而短信只能发文字,于是出现了能够发图片的彩信,但不管短信还是彩信,资费都太贵 ...

  5. android中点击加号动画,android animation之scale 缩放(仿微信加号弹出菜单的动画效果)...

    仿微信 +号 处理事件:弹出菜单的动画效果--缩放(反义词) 放大效果(缩小的代码只需将fromXScale和toXScale,:fromYScale和toYScale变换) android:inte ...

  6. android 小练习(一) ---仿微信UI主界面

    ActionBar 相信大家都用过微信,微信的界面我们从上往下看,首先是一个ActionBar,并且自定义了ActionProvider,就是那个"加号",里面有五个子菜单.今天就 ...

  7. android 模仿微信布局,【Android初学者】框架布局:仿微信页面制作

    学习Android有一段时间了,跟大家分享一下经验吧! 如果有错误的地方,有更好的方法,麻烦大家留言指导! 工具:studio2.2,虚拟机版本:4.3,API 18(感觉比5.1的稳定啊!) 例子是 ...

  8. android相片拼板源码,实现仿微信拍照和选取相片(转自网络)

    1,首先MainActivity package com.example.picpopupwindow; import android.app.Activity; import android.con ...

  9. Android实现首字母导航条(仿微信)

    本博客介绍Android实现首字母导航条,先看张效果图,具体怎么实现看代码吧 具体的步骤 1.整体布局的显示 2. 实现A-Z的分组 3. 自定义A-Z的导航条 4. 中间显示/隐藏触摸到导航条具体的 ...

最新文章

  1. vue-vue项目中mock.js的使用
  2. shell脚本的exit问题(退出脚本还是退出终端)
  3. ofbiz mysql 中文安装_ofbiz的部署及安装问题解决办法
  4. 送福利 | 送书5本《ASP.NET Core项目开发实战入门》带你走进ASP.NET Core开发
  5. Assign the task HDU - 3974(线段树+dfs建树+单点查询+区间修改)
  6. npm 安装axios和使用增删改查
  7. Eclipse中activiti插件的安装
  8. mysql in 有序_mysql中的in排序 mysql按in中顺序来排序
  9. QT安装后编译错误怎么办?
  10. 物质环境、符号还是认知模型?——谈韩礼德、马丁、范迪克的语境观
  11. 祝福 Eric 的下一段旅程|Flutter 3.3 现已发布
  12. uni-app—使用vscode创建小程序项目(图文)
  13. 自然保护区相关矢量数据下载
  14. 自定义一个可滑动时间刻度尺
  15. 在Ansible中缓存事实
  16. cluster_acc计算
  17. 人效提高350%,基于KICP搭建的营销套电客服机器人,让欧派家居赢在起点
  18. 利用Python画随机水墨图
  19. 数据库DDL(Data Definition Language,数据定义语言)知识点
  20. android沙漏,android沙漏

热门文章

  1. POJ3614奶牛晒阳光DINIC或者贪心
  2. hdu 5045 费用流
  3. hdu3768 spfa+全排列
  4. 计算机网络第四章:网络层
  5. 【数字信号处理】线性时不变系统 LTI “ 输入 “ 与 “ 输出 “ 之间的关系 ( 周期性分析 | 卷积运算规律 | 交换律 | 结合律 | 分配率 | 冲击不变性 )
  6. 【数据挖掘】分类任务简介 ( 分类概念 | 分类和预测 | 分类过程 | 训练集 | 测试集 | 数据预处理 | 有监督学习 )
  7. 关闭子页面刷新父页面,不需要弹出确认窗口
  8. [POJ 3345] Bribing FIPA
  9. 关于动态门户WEB博雅互动的源代码(HTML+CSS+javascript)
  10. hs_err_pid