Android项目实战(二十三):仿QQ设置App全局字体大小

原文:Android项目实战(二十三):仿QQ设置App全局字体大小

一、项目需求:

因为产品对象用于中老年人,所以产品设计添加了APP全局字体调整大小功能。

这里仿做QQ设置字体大小的功能。

QQ实现的效果是,滚动下面的seekbar,当只有seekbar到达某一个刻度的时候,这时候上部分的效果展示部分会改变文字大小,

但是在拖动过程中字体不会改变。关闭此界面,就可以看到改变文字后app整体的实际文字大小效果了。

-----------------------------------------------------------------------------------------------------------------------------

二、理清一下实现思路:

1、先将一个APP内所有的文本设置级别,大概3--5个级别(具体看项目需求),比如标题栏的TextView我们给他设置级别1(默认24sp)  ,类似设置 级别2(默认22sp)等等。

  这样做的目的可以方便的我们设置,如果每个Textview大小都乱乱的,那这个文字大小改变的功能也没什么意义了。

2、创建一个类Constant,类中创建一个静态变量,这个变量用于记录当我们拖动seekbar的时候 对应改变。取值范围就是我们seekbar的界点。

Demo我们限制文字大小有四个界点:小、标准、大、特大。

那么静态变量 TEXT_SIZE 取值就有0,1,2,3

 public static int TEXT_SIZE = 0;

3、滑动seekbar,当达到界点的时候,改变静态变量TEXT_SIZE的值,并且刷新列表适配器(这个列表是展示文字大小效果的,所以数据是我们自己写死的,

要求达到某个界点才会刷新适配器,绝不可能seekbar有滑动操作我们就执行刷新适配器的)

4、在退出设置字体界面的时候,用sharedPreferences保存,每次进入app的时候读取。

这样在每个Activity或者Fragment 创建View的过程中在 TextView创建的时候给控件动态设置文字的大小

textview.setTextSize(级别默认文字大小+seekbar级别*3);

思路就是这么简单,看懂的可以自己去实现了,有点懵的看下面的例子来深入了解下。

整体思路就是:  一个标记变量,记录要显示文字大小的级别,sharedpreference保存。然后在每个要打开的新的界面创建View的过程中 给TextView动态设置文字大小

注意:不是我修改文字大小之后,整个APP所有界面的TextView都立马改变。

-----------------------------------------------------------------------------------------------------------------------------

三、代码实现

1、首先就是这个SeekBar控件,上面需要有刻度,需要有文字,显然我们用android提供的自带的SeekBar控件已经不满足我们的需求了。

但是,这里我找到了一个很好的自定义控件可以完美的实现这个问题:

资料来源:   Android 自定义带刻度的seekbar

  这里我加了一些注释

  1 public class CustomSeekbar extends View {
  2     private final String TAG = "CustomSeekbar";
  3     private int width;
  4     private int height;
  5     private int downX = 0;
  6     private int downY = 0;
  7     private int upX = 0;
  8     private int upY = 0;
  9     private int moveX = 0;
 10     private int moveY = 0;
 11     private float scale = 0;
 12     private int perWidth = 0;
 13     private Paint mPaint;
 14     private Paint mTextPaint;
 15     private Paint buttonPaint;
 16     private Canvas canvas;
 17     private Bitmap bitmap;
 18     private Bitmap thumb;
 19     private Bitmap spot;
 20     private Bitmap spot_on;
 21     private int hotarea = 100;//点击的热区
 22     private int cur_sections = 2;
 23     private ResponseOnTouch responseOnTouch;
 24     private int bitMapHeight = 38;//第一个点的起始位置起始,图片的长宽是76,所以取一半的距离
 25     private int textMove = 60;//字与下方点的距离,因为字体字体是40px,再加上10的间隔
 26     private int[] colors = new int[]{0xffdf5600,0x33000000};//进度条的橙色,进度条的灰色,字体的灰色
 27     private int textSize;
 28     private int circleRadius;
 29     private ArrayList<String> section_title;
 30     public CustomSeekbar(Context context) {
 31         super(context);
 32     }
 33     public CustomSeekbar(Context context, AttributeSet attrs) {
 34         this(context, attrs, 0);
 35     }
 36     public CustomSeekbar(Context context, AttributeSet attrs, int defStyleAttr) {
 37         super(context, attrs, defStyleAttr);
 38         cur_sections = 0;
 39         bitmap = Bitmap.createBitmap(900, 1100, Bitmap.Config.ARGB_8888);
 40         canvas = new Canvas();
 41         canvas.setBitmap(bitmap);
 42         thumb = BitmapFactory.decodeResource(getResources(), R.mipmap.img_setting_seekbar_thumbe_large);   //这个是滑动图标
 43         spot = BitmapFactory.decodeResource(getResources(),R.mipmap.img_setting_seekbar_thumbe);            //这个是未滑动到的界点的图标
 44         spot_on = BitmapFactory.decodeResource(getResources(),R.mipmap.img_setting_seekbar_thumbe);         //这个是已经滑动过的界点的图标
 45         bitMapHeight = thumb.getHeight()/2;   //这里影响点中的图标的位置  这个正好 不用改
 46         textMove = bitMapHeight+ 5;   //xqx  这里参数大小要改,不是固定的,具体看项目效果
 47         textSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20, getResources().getDisplayMetrics());   //文字大小,第二个参数个人设置
 48         circleRadius = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3, getResources().getDisplayMetrics());
 49         mPaint = new Paint(Paint.DITHER_FLAG);
 50         mPaint.setAntiAlias(true);//锯齿不显示
 51         mPaint.setStrokeWidth(3);
 52         mTextPaint = new Paint(Paint.DITHER_FLAG);
 53         mTextPaint.setAntiAlias(true);
 54         mTextPaint.setTextSize(textSize);
 55         mTextPaint.setColor(0xffb5b5b4);
 56         buttonPaint = new Paint(Paint.DITHER_FLAG);
 57         buttonPaint.setAntiAlias(true);
 58
 59     }
 60     /**
 61      * 实例化后调用,设置bar的段数和文字
 62      */
 63     public void initData(ArrayList<String> section){
 64         if(section != null){
 65             section_title = section;
 66         }else {
 67             //如果没有传入正确的分类级别数据,则默认使用“低”“中”“高”
 68             String[] str = new String[]{"低", "中", "高"};
 69             section_title = new ArrayList<String>();
 70             for (int i = 0; i < str.length; i++) {
 71                 section_title.add(str[i]);
 72             }
 73         }
 74     }
 75
 76     @Override
 77     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 78         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 79
 80         int widthMode = MeasureSpec.getMode(widthMeasureSpec);
 81         int widthSize = MeasureSpec.getSize(widthMeasureSpec);
 82         int heightMode = MeasureSpec.getMode(heightMeasureSpec);
 83         int heightSize = MeasureSpec.getSize(heightMeasureSpec);
 84
 85         width = widthSize;
 86         float scaleX = widthSize / 1080;
 87         float scaleY = heightSize / 1920;
 88         scale = Math.max(scaleX,scaleY);
 89         //控件的高度
 90         //height = 185;
 91         height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 62, getResources().getDisplayMetrics());
 92         setMeasuredDimension(width, height);
 93         width = width-bitMapHeight/2;
 94         perWidth = (width - section_title.size()*spot.getWidth() - thumb.getWidth()/2) / (section_title.size()-1);
 95         hotarea = perWidth/2;
 96     }
 97
 98     @Override
 99     protected void onDraw(Canvas canvas) {
100         super.onDraw(canvas);
101         mPaint.setColor(Color.WHITE);
102         mPaint.setStyle(Paint.Style.FILL);
103         mPaint.setAlpha(0);
104         canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);
105         canvas.drawBitmap(bitmap, 0, 0, null);
106         mPaint.setAlpha(255);
107         mPaint.setColor(colors[1]);
108         canvas.drawLine(bitMapHeight, height * 2 / 3, width - bitMapHeight - spot_on.getWidth() / 2, height * 2 / 3, mPaint);
109         int section = 0;
110         while(section < section_title.size()){
111             if(section < cur_sections) {
112                 mPaint.setColor(colors[0]);
113                 canvas.drawLine(thumb.getWidth()/2 + section * perWidth + (section+1) * spot_on.getWidth(),height * 2 / 3,
114                         thumb.getWidth()/2 + section * perWidth + (section+1) * spot_on.getWidth() + perWidth,height * 2 / 3,mPaint);
115                 canvas.drawBitmap(spot_on, thumb.getWidth()/2 + section * perWidth + section * spot_on.getWidth(),height * 2 / 3 - spot_on.getHeight()/2,mPaint);
116             }else{
117                 mPaint.setAlpha(255);
118                 if(section == section_title.size()-1){
119                     canvas.drawBitmap(spot,  width - spot_on.getWidth() - bitMapHeight/2, height * 2 / 3 - spot.getHeight() / 2, mPaint);
120                 }else {
121                     canvas.drawBitmap(spot, thumb.getWidth()/2 + section * perWidth + section * spot_on.getWidth(), height * 2 / 3 - spot.getHeight() / 2, mPaint);
122                 }
123             }
124
125             if(section == section_title.size()-1) {
126                 canvas.drawText(section_title.get(section), width - spot_on.getWidth()- bitMapHeight/4 - textSize / 2, height * 2 / 3 - textMove, mTextPaint);
127             }else{
128                 canvas.drawText(section_title.get(section), thumb.getWidth()/2 + section * perWidth + section * spot_on.getWidth(), height * 2 / 3 - textMove, mTextPaint);
129             }
130             section++;
131         }
132         if(cur_sections == section_title.size()-1){
133             canvas.drawBitmap(thumb, width - spot_on.getWidth() - bitMapHeight/2 - thumb.getWidth() / 2,
134                     height * 2 / 3 - bitMapHeight, buttonPaint);
135         }else {
136             canvas.drawBitmap(thumb, thumb.getWidth()/2 + cur_sections * perWidth + cur_sections * spot_on.getWidth() - thumb.getWidth()/4 ,
137                     height * 2 / 3 - bitMapHeight, buttonPaint);
138         }
139     }
140
141     @Override
142     public boolean onTouchEvent(MotionEvent event) {
143         super.onTouchEvent(event);
144         switch (event.getAction()) {
145             case MotionEvent.ACTION_DOWN:
146                 thumb = BitmapFactory.decodeResource(getResources(), R.mipmap.img_setting_seekbar_thumbe_large);
147                 downX = (int) event.getX();
148                 downY = (int) event.getY();
149                 responseTouch(downX, downY);
150                 break;
151             case MotionEvent.ACTION_MOVE:
152                 thumb = BitmapFactory.decodeResource(getResources(), R.mipmap.img_setting_seekbar_thumbe_large);
153                 moveX = (int) event.getX();
154                 moveY = (int) event.getY();
155                 responseTouch(moveX, moveY);
156                 break;
157             case MotionEvent.ACTION_UP:
158                 thumb = BitmapFactory.decodeResource(getResources(), R.mipmap.img_setting_seekbar_thumbe_large);
159                 upX = (int) event.getX();
160                 upY = (int) event.getY();
161                 responseTouch(upX, upY);
162                 responseOnTouch.onTouchResponse(cur_sections);
163                 break;
164         }
165         return true;
166     }
167     private void responseTouch(int x, int y){
168         if(x <= width-bitMapHeight/2) {
169             cur_sections = (x + perWidth / 3) / perWidth;
170         }else{
171             cur_sections = section_title.size()-1;
172         }
173         invalidate();
174     }
175
176     //设置监听
177     public void setResponseOnTouch(ResponseOnTouch response){
178         //注意 ,这里是接口,实现你到达界点的监听事件,因为这个自定义控件继承的View而不是SeekBar,所以只能使用接口实现监听
179         responseOnTouch = response;
180     }
181
182
183     //设置进度
184     public void setProgress(int progress){
185         cur_sections = progress;
186         invalidate();
187     }
188 }

CustomSeekbar.class

2、根据这个自定义CustomSeekbar控件,我们首先要建一个接口

public interface ResponseOnTouch {
    public void onTouchResponse(int volume);
}

3、创建一个类。设置一个静态属性

public class Constant {    public static int TEXT_SIZE = 0;}

4、接下来写字体设置后的效果界面:qq的效果界面有两个,一个是聊天的界面,一个是列表的界面。

这里我们只展示列表的界面

列表代码就不展示了

直接看如何使用CustomSeekbar

 1         private CustomSeekbar seekBar;
 2         seekBar = (CustomSeekbar) findViewById(R.id.progressBar);
 3      //这个集合用于给自定义SeekBar设置界点级别,集合里有几个数据,就有几个界点
 4         ArrayList<String> volume_sections = new ArrayList<String>();
 5         volume_sections.add("小");
 6         volume_sections.add("标准");
 7         volume_sections.add("大");
 8         volume_sections.add("特大");
 9         seekBar.initData(volume_sections);
10         seekBar.setProgress(0); //设置默认级别
11
12
13         seekBar.setResponseOnTouch(this);//activity实现了下面的接口ResponseOnTouch,每次touch会回调onTouchResponse

实现接口:

@Override
    public void onTouchResponse(int volume) {
        Toast.makeText(this,"volume-->"+volume,Toast.LENGTH_SHORT).show();
        //参数volume就是级别,如果我们集合有4个数据 那么volume的取值就为0、1、2、3     Constant.TEXT_SIZE = volume;     //这里写sharedpreferences保存该静态变量     //刷新列表 ,查看文字改变后的效果  
        adapter.notifyDataSetChanged();
    }

列表适配器中对textview设置大小的代码:

 holder.community_doctor_name.setTextSize(该TextView控件级别默认文字大小+ Constant.TEXT_SIZE*5);

效果图:

后续补上。

个人思路,实现的局限性是有的,大家有修改意见欢迎提出。

原文地址:https://www.cnblogs.com/lonelyxmas/p/8970196.html

时间: 2024-08-06 20:55:31

Android项目实战(二十三):仿QQ设置App全局字体大小的相关文章

Android项目实战(十三):浅谈EventBus

原文:Android项目实战(十三):浅谈EventBus 概述: EventBus是一款针对Android优化的发布/订阅事件总线. 主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service. 线程之间传递消息.优点是开销小,代码更优雅,以及将发送者和接收者解耦. ---------------------------------------------------------------------------------------

Android项目实战(二十九):酒店预定日期选择

原文:Android项目实战(二十九):酒店预定日期选择 先看需求效果图:              几个需求点: 1.显示当月以及下个月的日历 (可自行拓展更多月份) 2.首次点击选择"开始日期",再次点击选择"结束日期" (1).如果"开始日期" "结束日期" 相同  (2).如果"开始日期" "结束日期" 不同,且"结束日期" 晚于 "开始日期&quo

Android项目实战(十七):QQ空间实现(二)—— 分享功能 / 弹出PopupWindow

原文:Android项目实战(十七):QQ空间实现(二)-- 分享功能 / 弹出PopupWindow 这是一张QQ空间说说详情的截图. 分析: 1.点击右上角三个点的图标,在界面底部弹出一个区域,这个区域有一些按钮提供给我们操作 2.当该区域出现的时候,详情界面便灰了,也说成透明度变化了 3.当任意选了一个按钮或者点击了该区域以外的部分,该区域消失,灰色界面变回亮白色,并执行点击的按钮对应的操作 显然,这个功能我们需要用PopupWindow实现更好~ --------------------

android 自定义控件二之仿QQ长按删除

自定义Dialog 1.先上个效果图: 虽然效果丑了点,但主要学习修改已有的控件,例如修改Dialog控件 2.一些基本的只是进行了解 Dialog: theme是Dialog的样式,常用样式为: <style name="MyDialogStyle" parent="@android:Theme.Dialog"> <item name="android:windowFrame">@null</item> &l

(转载)Android项目实战(三十二):圆角对话框Dialog

Android项目实战(三十二):圆角对话框Dialog 前言: 项目中多处用到对话框,用系统对话框太难看,就自己写一个自定义对话框. 对话框包括:1.圆角 2.app图标 , 提示文本,关闭对话框的"确定"按钮 难点:1.对话框边框圆角显示 2.考虑到提示文本字数不确定,在不影响美观的情况下,需要在一行内显示提示的文字信息   3.设置对话框的宽和高 技术储备: 1.安卓开发_使用AlertDialog实现对话框    知道AlertDialog有setView(view) ,Dia

Android项目实战(二):安卓应用程序退出的三种方法

原文:Android项目实战(二):安卓应用程序退出的三种方法 现在的APP退出的时候都不是让用户点击了“后退键”就退出.防止用户点错了后退键而造成的用户体检不好. 一年前搞的Demo代码不见了,重新写下就当是复习和以后直接拿来用把 目前流行的解决一般分为两种: 一.按一次后退键显示一个对话框决定是否退出 1 @Override 2 public boolean onKeyDown(int keyCode, KeyEvent event) { 3 // TODO Auto-generated m

Android项目实战(三十二):圆角对话框Dialog

原文:Android项目实战(三十二):圆角对话框Dialog 前言: 项目中多处用到对话框,用系统对话框太难看,就自己写一个自定义对话框. 对话框包括:1.圆角 2.app图标 , 提示文本,关闭对话框的"确定"按钮 难点:1.对话框边框圆角显示 2.考虑到提示文本字数不确定,在不影响美观的情况下,需要在一行内显示提示的文字信息   3.设置对话框的宽和高 技术储备: 1.安卓开发_使用AlertDialog实现对话框    知道AlertDialog有setView(view) ,

Android项目实战(四十二):启动页优化,去除短暂白屏或黑屏

原文:Android项目实战(四十二):启动页优化,去除短暂白屏或黑屏 大家会发现一个空项目,从手机桌面打开app是秒启动.但是对于自己开发的项目,有时会发现打开app的时候,会有短暂的1秒--2秒的白屏或者黑屏,然后才进入到程序界面. 个人理解为我们自己实现的Application文件里面做了较多的初始化操作,当这些初始化操作完成后才进入到第一个Activity,这段初始化的时间因为没有界面,应用便会因为主题的类别而显示白屏或者黑屏. 构成白屏/黑屏的原因代码如下: /*** @author

Android项目实战(二十八):Zxing二维码实现及优化

原文:Android项目实战(二十八):Zxing二维码实现及优化 前言: 多年之前接触过zxing实现二维码,没想到今日项目中再此使用竟然使用的还是zxing,百度之,竟是如此牛的玩意. 当然,项目中我们也许只会用到二维码的扫描和生成两个功能,所以不必下载完整的jar包,使用简化版的即可,下文可见. 这篇文章讲述:1.如果快速在项目中集成zxing,实现扫描和生成二维码功能 2.根据项目需求去修改源码实现我们的要求并进行优化 一.快速集成zxing二维码 1.下载库文件 : http://do