FontResize

FontResize是一个仿微信/支付宝 字体大小 调整控件的库

gradle依赖

implementation 'com.ljx.view:fontresize:1.0.1'

源码下载 该库里面只有一个类FontResizeView,故不用担心库很大。

效果图

属性说明

<declare-styleable name="FontResizeView"><attr name="minSize" format="reference|dimension" /> <!--最小size--><attr name="maxSize" format="reference|dimension" /> <!--最大size--><attr name="totalGrade" format="integer" />   <!--可调整的等级、即总的等级--><attr name="standardGrade" format="integer" />  <!--标准等级--><attr name="leftText" format="reference|string" />  <!--左边文本,默认为 'A'--><attr name="middleText" format="reference|string" />  <!--中间文本,默认为 '标准'--><attr name="rightText" format="reference|string" />  <!--右边文本,默认为 'A'--><attr name="leftTextColor" format="reference|color" />  <!--左边文本颜色,默认为全黑--><attr name="middleTextColor" format="reference|color" />  <!--中间文本颜色,默认为全黑--><attr name="rightTextColor" format="reference|color" />  <!--右边文本颜色,默认为全黑--><attr name="sliderRadius" format="reference|dimension" />  <!--滑块半径--><attr name="sliderColor" format="reference|color" />  <!--滑块颜色--><attr name="sliderShadowColor" format="reference|color" />  <!--滑块边缘阴影颜色--><attr name="lineColor" format="reference|color" />  <!--线条颜色--><attr name="lineStrokeWidth" format="reference|dimension" />  <!--线条宽度,即粗细程度--><attr name="horizontalLineLength" format="reference|dimension" />  <!--横向线条长度--><attr name="verticalLineLength" format="reference|dimension" />  <!--纵向线条长度--></declare-styleable>

xml配置

<com.ljx.view.FontResizeViewandroid:id="@+id/font_resize_view"android:layout_width="match_parent"android:layout_height="140dp"android:background="@android:color/white"app:maxSize="25sp"app:minSize="13sp"app:sliderColor="@android:color/white"app:sliderRadius="12dp"app:standardGrade="2"app:totalGrade="7" />

设置回调

FontResizeView fontResizeView = findViewById(R.id.font_resize_view);
fontResizeView.setOnFontChangeListener(new OnFontChangeListener() {@Overridepublic void onFontChange(float fontSize) {//字体size改变回调  单位:sp}
});

这样配置过后,代码跑起来效果就跟上面的 gif 动图一样

我们把所有属性都加上,看看效果

<com.ljx.view.FontResizeViewandroid:id="@+id/font_resize_view"android:layout_width="match_parent"android:layout_height="140dp"android:background="@android:color/white"app:horizontalLineLength="300dp"app:leftText="AA"app:leftTextColor="#FF0000"app:lineColor="#009999"app:lineStrokeWidth="2dp"app:maxSize="31sp"app:minSize="15sp"app:middleText="标准1"app:middleTextColor="#00FF00"app:rightText="AAA"app:rightTextColor="#0000FF"app:sliderColor="@android:color/white"app:sliderRadius="13dp"app:sliderShadowColor="#FF0000"app:standardGrade="3"app:totalGrade="9"app:verticalLineLength="15dp" />

效果如下

相信以上属性已经能满足大部分场景,如果不能满足您的场景,请提出您的需求,我会第一时间回应您。

强烈推荐

RxHttp 一条链发送请求,新一代Http请求神器(一)

RxLife 一款轻量级别的RxJava生命周期管理库(一)

Android 史上最优雅的实现文件上传、下载及进度的监听

最后,放出源码

/*** 字体大小调整控件* User: ljx* Date: 2018/05/11* Time: 09:53*/
public class FontResizeView extends View {//默认线条颜色private static final int DEFAULT_LINE_COLOR = Color.parseColor("#222222");private boolean isCoincide;//是否重合private int width, height;//FontAdjustView的宽高private float minSize;//最小字体大小private float maxSize;//最大字体大小private float standardSize;//标准字体大小private String leftText;   //左边文本private String middleText; //中间文本private String rightText;  //右边文本private int leftTextColor;     //左边文本颜色private int middleTextColor;   //中间文本颜色private int rightTextColor;    //右边文本颜色private int totalGrade;             //总的等级private int standardGrade;          //标准等级private int lineColor;              //线条颜色private int horizontalLineLength;   //横向线段长度private int verticalLineLength;     //纵向线段长度private int lineStrokeWidth;        //线条宽度private int lineAverageWidth;       //每段水平线条的长度private int   sliderGrade;       //滑块等级private int   sliderColor;       //滑块颜色private int   sliderShadowColor; //滑块阴影颜色private Point sliderPoint;       //滑块位置private Paint                mPaint;//画笔private Line                 mHorizontalLine;   //一条横线private Line[]               mVerticalLines;    //n条竖线private GestureDetector      mGestureDetector;  //手势检测private OnFontChangeListener onFontChangeListener; //字体size改变监听器public FontResizeView(Context context) {this(context, null);}public FontResizeView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public FontResizeView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);int padding = dp2px(35);setPadding(padding, padding, padding, padding);TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.FontResizeView);minSize = ta.getDimension(R.styleable.FontResizeView_minSize, dp2px(15));maxSize = ta.getDimension(R.styleable.FontResizeView_maxSize, dp2px(25));totalGrade = ta.getInt(R.styleable.FontResizeView_totalGrade, 6);standardGrade = ta.getInt(R.styleable.FontResizeView_standardGrade, 2);if (standardGrade < 1 || standardGrade > 6) {standardGrade = 1;}sliderGrade = standardGrade;leftText = ta.getString(R.styleable.FontResizeView_leftText);if (TextUtils.isEmpty(leftText)) leftText = "A";middleText = ta.getString(R.styleable.FontResizeView_middleText);if (TextUtils.isEmpty(middleText))middleText = context.getString(R.string.font_resize_standard);rightText = ta.getString(R.styleable.FontResizeView_rightText);if (TextUtils.isEmpty(rightText)) rightText = "A";leftTextColor = ta.getColor(R.styleable.FontResizeView_leftTextColor, Color.BLACK);middleTextColor = ta.getColor(R.styleable.FontResizeView_middleTextColor, Color.BLACK);rightTextColor = ta.getColor(R.styleable.FontResizeView_rightTextColor, Color.BLACK);lineColor = ta.getColor(R.styleable.FontResizeView_lineColor, DEFAULT_LINE_COLOR);lineStrokeWidth = ta.getDimensionPixelOffset(R.styleable.FontResizeView_lineStrokeWidth, dp2px(0.5f));horizontalLineLength = ta.getDimensionPixelOffset(R.styleable.FontResizeView_horizontalLineLength, -1);verticalLineLength = ta.getDimensionPixelOffset(R.styleable.FontResizeView_verticalLineLength, -1);sliderColor = ta.getColor(R.styleable.FontResizeView_sliderColor, Color.WHITE);sliderShadowColor = ta.getColor(R.styleable.FontResizeView_sliderShadowColor, Color.GRAY);float sliderRadius = ta.getDimension(R.styleable.FontResizeView_sliderRadius, dp2px(25));ta.recycle();mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint.setStyle(Paint.Style.FILL);width = getResources().getDisplayMetrics().widthPixels;height = dp2px(140);standardSize = (maxSize - minSize) / (totalGrade - 1) * (standardGrade - 1) + minSize;mHorizontalLine = new Line();mVerticalLines = new Line[totalGrade];for (int i = 0; i < mVerticalLines.length; i++) {mVerticalLines[i] = new Line();}sliderPoint = new Point(sliderRadius);mGestureDetector = new GestureDetector(context, gestureListener);}GestureDetector.SimpleOnGestureListener gestureListener = new GestureDetector.SimpleOnGestureListener() {@Overridepublic boolean onDown(MotionEvent e) {isCoincide = sliderPoint.coincide(e.getX(), e.getY());getParent().requestDisallowInterceptTouchEvent(true);return super.onDown(e);}/*** 单击事件*/@Overridepublic boolean onSingleTapUp(MotionEvent e) {final Line horizontalLine = mHorizontalLine;float x = e.getX();if (x > horizontalLine.stopX) {x = horizontalLine.stopX;} else if (x < horizontalLine.startX) {x = horizontalLine.startX;}moveSlider(x - horizontalLine.startX, true);return true;}@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {getParent().requestDisallowInterceptTouchEvent(true);if (isCoincide) {float x = sliderPoint.getX();setSliderPointX(x - distanceX, false);postInvalidate();return true;}return super.onScroll(e1, e2, distanceX, distanceY);}};@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int specWidthSize = MeasureSpec.getSize(widthMeasureSpec);int specWidthMode = MeasureSpec.getMode(widthMeasureSpec);int specHeightSize = MeasureSpec.getSize(heightMeasureSpec);int specHeightMode = MeasureSpec.getMode(heightMeasureSpec);switch (specWidthMode) {case MeasureSpec.UNSPECIFIED:case MeasureSpec.AT_MOST:width = Math.min(width, specWidthSize);break;case MeasureSpec.EXACTLY:width = specWidthSize;break;}switch (specHeightMode) {case MeasureSpec.UNSPECIFIED:case MeasureSpec.AT_MOST:height = Math.min(height, specHeightSize);break;case MeasureSpec.EXACTLY:height = specHeightSize;break;}setMeasuredDimension(width, height);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);if (horizontalLineLength == -1)horizontalLineLength = w - getPaddingLeft() - getPaddingRight();if (verticalLineLength == -1) verticalLineLength = dp2px(10);lineAverageWidth = horizontalLineLength / (totalGrade - 1);//初始化横线起点位置int horizontalLineStartX = (width - horizontalLineLength) / 2;int horizontalLineStartY = (int) (height * 0.6);//初始化横线起点、终点位置mHorizontalLine.set(horizontalLineStartX, horizontalLineStartY, horizontalLineStartX + horizontalLineLength, horizontalLineStartY);float lineAverageWidth = horizontalLineLength * 1.0f / (totalGrade - 1);final Line[] verticalLines = mVerticalLines;for (int i = 0; i < verticalLines.length; i++) {float startX = horizontalLineStartX + lineAverageWidth * i;verticalLines[i].set(startX, horizontalLineStartY - verticalLineLength / 2f, startX, horizontalLineStartY + verticalLineLength / 2f);}//初始化滑块的等级及位置sliderPoint.setGrade(sliderGrade - 1);setSliderPointX(verticalLines[sliderGrade - 1].startX, true);sliderPoint.setY(verticalLines[sliderGrade - 1].startY + verticalLines[sliderGrade - 1].getHeight() / 2);}@Overrideprotected void onDraw(Canvas canvas) {final Line horizontalLine = mHorizontalLine;mPaint.setColor(lineColor);mPaint.setStrokeWidth(lineStrokeWidth);//绘制横线canvas.drawLine(horizontalLine.startX, horizontalLine.startY, horizontalLine.stopX, horizontalLine.stopY, mPaint);//绘制线段for (Line line : mVerticalLines) {canvas.drawLine(line.startX, line.startY, line.stopX, line.stopY, mPaint);}//绘制左边文本mPaint.setColor(leftTextColor);mPaint.setTextSize(minSize);float width = mPaint.measureText(leftText);float startY = horizontalLine.startY - dp2px(20);canvas.drawText(leftText, horizontalLine.startX - width / 2, startY, mPaint);//绘制右边文本mPaint.setColor(rightTextColor);mPaint.setTextSize(maxSize);width = mPaint.measureText(rightText);canvas.drawText(rightText, horizontalLine.stopX - width / 2, startY, mPaint);//绘制中间文本mPaint.setColor(middleTextColor);mPaint.setTextSize(standardSize);width = mPaint.measureText(middleText);float startX = mVerticalLines[standardGrade - 1].startX - width / 2;if (standardGrade == 1 || standardGrade == totalGrade) {startY -= dp2px(7) + standardSize;}canvas.drawText(middleText, startX, startY, mPaint);//绘制 滑块mPaint.setColor(sliderColor);float radius = sliderPoint.getRadius();mPaint.setShadowLayer(10f, 2, 2, sliderShadowColor);canvas.drawCircle(sliderPoint.getX(), sliderPoint.getY(), radius, mPaint);mPaint.setShadowLayer(0, 0, 0, sliderShadowColor);//关闭阴影}@Overridepublic boolean onTouchEvent(MotionEvent event) {if (mGestureDetector.onTouchEvent(event)) {return true;}if (event.getAction() == MotionEvent.ACTION_UP && isCoincide) {//手指抬起时,滑块不在整点,则移动到整点float x = sliderPoint.getX() - mHorizontalLine.startX;moveSlider(x, false);}return true;}/*** 移动滑块*/private void moveSlider(float destX, final boolean isClick) {int grade = (int) destX / lineAverageWidth;//目标等级float remainder = destX % lineAverageWidth;if (remainder > lineAverageWidth / 2) grade++;final int tempGrade = grade;int gradeDiffer = Math.abs(sliderPoint.getGrade() - tempGrade);if (gradeDiffer == 0) {if (isClick) return;gradeDiffer = 1;}ValueAnimator animator = ValueAnimator.ofFloat(sliderPoint.getX(), mVerticalLines[tempGrade].startX);animator.setDuration(100 + gradeDiffer * 30);animator.setInterpolator(new AccelerateDecelerateInterpolator());animator.addUpdateListener(new AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {Float value = (Float) animation.getAnimatedValue();//如果是单击触发的移动事件,动画未结束前仅更新滑块的位置,动画结束后再更新滑块的等级setSliderPointX(value, isClick);postInvalidate();}});animator.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {setSliderPointX(mVerticalLines[tempGrade].startX, false);}});animator.start();}/*** 设置滑块X坐标的统一入口** @param onlySetX 是否仅仅更新滑块的位置*/private void setSliderPointX(float x, boolean onlySetX) {float horizontalLineStartX = mHorizontalLine.startX;float horizontalLineStopX = mHorizontalLine.stopX;if (x < horizontalLineStartX) {x = horizontalLineStartX;} else if (x > horizontalLineStopX) {x = horizontalLineStopX;}sliderPoint.setX(x);if (onlySetX) return;int oldGrade = sliderPoint.getGrade();int newGrade = (int) (x - horizontalLineStartX) / lineAverageWidth;if (oldGrade == newGrade) return;sliderPoint.setGrade(newGrade);if (onFontChangeListener != null) {float size = (maxSize - minSize) / (totalGrade - 1);float sp = (minSize + size * newGrade) / getResources().getDisplayMetrics().scaledDensity;onFontChangeListener.onFontChange(sp);}}/*** @return 返回当前设置的字体大小  单位 :sp*/public float getFontSize() {float size = (maxSize - minSize) / (totalGrade - 1);return (minSize + size * (sliderGrade - 1)) / getResources().getDisplayMetrics().scaledDensity;}/*** 设置当前字体大小** @param fontSize 字体大小 单位 :sp*/public void setFontSize(float fontSize) {fontSize *= getResources().getDisplayMetrics().scaledDensity;int grade = (int) ((fontSize - minSize) / ((maxSize - minSize) / (totalGrade - 1))) + 1;setSliderGrade(grade);}/*** 设置滑块等级** @param grade 滑块等级*/public void setSliderGrade(int grade) {if (grade < 0) grade = 1;if (grade > totalGrade) grade = totalGrade;sliderGrade = grade;}private int dp2px(float dipValue) {final float scale = getContext().getResources().getDisplayMetrics().density;return (int) (dipValue * scale + 0.5f);}public void setOnFontChangeListener(OnFontChangeListener onFontChangeListener) {this.onFontChangeListener = onFontChangeListener;}public interface OnFontChangeListener {/*** @param fontSize 字体大小、单位sp*/void onFontChange(float fontSize);}class Point {//滑块位置及半径float x;float y;float radius;int grade; //滑块等级Point(float radius) {this.radius = radius;}float getX() {return x;}void setX(float x) {this.x = x;}float getY() {return y;}void setY(float y) {this.y = y;}float getRadius() {return radius;}int getGrade() {return grade;}void setGrade(int grade) {this.grade = grade;}//判断手指按下的点是否与滑块重合boolean coincide(float movingX, float movingY) {//开方,如果两点之间的距离小于规定的半径r则定义为重合return Math.sqrt((x - movingX) * (x - movingX)+ (y - movingY) * (y - movingY)) < radius + dp2px(20);}}class Line {float startX;float startY;float stopX;float stopY;void set(float startX, float startY, float stopX, float stopY) {this.startX = startX;this.startY = startY;this.stopX = stopX;this.stopY = stopY;}float getHeight() {return Math.abs(stopY - startY);}}
}

本文为原创文章,如需转载,请注明出处,??。

Android 仿微信/支付宝 字体大小 调整控件相关推荐

  1. Android全局修改字体大小,Android 仿微信全局字体大小调整

    image 目录 一.前言 二.效果预览 三.实现步骤 1.自定义字体调整控件 2.滑动按钮改变当前页面预览字体大小 3.返回时,保存放大倍数并重启应用 4.初始化应用时配置字体放大倍数. 四.Dem ...

  2. aardio控件字体大小随控件缩放

    aardio窗体上的控件可以在属性里设置自适应大小,或者固定边距.九宫格布局等方法,这样控件的大小就会随着窗体大小变化而自动缩放调整了. 那么就有人问,控件里面的字体大小呢,也会随着缩放调整吗?怎么设 ...

  3. 云炬Android开发笔记 15评价晒单功能实现(自定义评分控件和仿微信自动多图选择控件)

    阅读目录 1. 晒单评价 1.1 点击页面跳转的实现 1.2 自定义评价订单的布局实现 1.3 星星布局的实现 2. 仿微信自动多图及删除控件 2.1 属性值及控件的定义 2.2 图片初始化方法onM ...

  4. android 语音播放工具,Android简易的仿微信聊天的语音播放控件

    说到Android音频播放,可谓108式,方案众多,这里有一篇总结Android几种播放音频的方式的文章,传送门.本文旨在熟悉MediaPlayer的使用,遂此控件封装采用MediaPlayer实现. ...

  5. Android自定义类似支付宝密码输入的控件

    前言:感觉自己记忆力不是很好,很多写过的东西容易忘记,所以还是写个博客记录一下,菜鸟一枚,望各位师傅指点. 嘿喂狗,来看我们要实现的效果(如果你说:"开发之前当然看不到效果,看个diao啊& ...

  6. Android仿keep运动轨迹动画,Android仿Keep运动休息倒计时圆形控件

    仿Keep运动休息倒计时控件,供大家参考,具体内容如下 源码 控件本身非常非常简单,唯一难点在于倒计时期间动态增减时长,如果说动态增减时长是瞬间完成的,倒也没什么难度,但是如果是需要花一定时间做动画的 ...

  7. Android仿饿了么加减控件,Flutter + Native混合栈仿饿了么APP

    前言 一个基于Flutter + Native混合开发的APP,请求数据均人为制造. 目前仅上传Android版本,iOS暂未上传 APK下载 Github地址 效果图: 实现功能: 首页 使用百度定 ...

  8. android 按钮回弹效果,Android仿IOS回弹效果 支持任何控件

    本文实例为大家分享了Android仿IOS回弹效果的具体代码,供大家参考,具体内容如下 效果图: 导入依赖: dependencies { // ... compile 'me.everything: ...

  9. android 布局回弹,Android仿IOS回弹效果 支持任何控件

    本文实例为大家分享了Android仿IOS回弹效果的具体代码,供大家参考,具体内容如下 效果图: 导入依赖: dependencies { // ... compile 'me.everything: ...

  10. css字体大小随控件,GitHub - Luren3/CssTextView: 这是基于TextView的扩展小控件,一个支持设置一段文字设置不同的颜色、大小、字体样式以及点击事件...

    设置文本内容其中文字的颜色 text文字 color颜色 startIndex开始位置 OnClickSpan点击事件 setTextArrColor(String text, int color) ...

最新文章

  1. 内核随记(三)--同步(2)【转】
  2. 经典文章解释apache与tomcat!看完秒懂
  3. sql server 隔离级别
  4. 安装epel源 失败:未知的名称或服务。 wget: 无法解析主机地址 “mirrors.aliyun.com”
  5. 微信模版消息 errmsg: 'invalid weapp pagepath hint: [OtU1OA0868a394]
  6. Vue全家桶 - 电商后台管理系统项目开发实录(详)
  7. win32api window2con 模块 -系统注册表操作
  8. PostgreSQL11.7逻辑复制的搭建
  9. 视觉平台搭建——光源选型介绍
  10. php中有关目录的几个函数 basename() dirname() pathinfo()
  11. udp wpf 权限_基于WPF开发局域网聊天工具,在用udp做上线功能时遇到的有关问题...
  12. 软考高级 真题 2011年上半年 信息系统项目管理师 案例分析
  13. Lettuce之RedisClusterClient使用以及源码分析
  14. 论文研读 —— 4. You Only Look Once Unified, Real-Time Object Detection (1/3)
  15. Flyway 报错:Detected applied migration not resolved locally:2和执行脚本错误
  16. java newline_Java BufferedWriter newLine()方法
  17. 【金融项目】尚融宝项目(九)
  18. Linux搭建FTP服务使用案例
  19. 移动100m宽带慢的要死_移动宽带的弊端,100兆光纤正常使用,一到晚上就犯病是为何?...
  20. modbus-tk学习笔记

热门文章

  1. python正则取反,一文搞定Python正则表达式
  2. 【量子机器学习】HHL算法: Quantum algorithm for solving linear systems of equations
  3. #web前端技术使用总结
  4. python整行列匹配,python-熊猫将行与列值匹配
  5. sfp寄存器_一种基于Linux系统读写光模块寄存器的方法与流程
  6. NRF52832-DFU升级-蓝牙抓包数据解析
  7. DroppyCtf靶机
  8. 面试官:兄弟,说说基本类型和包装类型的区别吧
  9. 【实习生面试】阿里前端实习生一面流程及题目
  10. 浅谈Java栈内存和堆内存