一,前言

心血来潮想着做一个颜色渐变带缩放的指示器,虽然网上很多大佬开源的指示器开源库,但如果一直都是使用别人造的轮子,那么对于自身的能力是毫无提升作用的,即使是参考别人的,然后自己动手写一遍那对于自身来说也是一种升华

二,思路

1,其实主要的内容就是自定义一个带颜色渐变的一个TextView,需要定义两个画笔,一个负责绘制未选中颜色,一个负责绘制选中时的颜色,各自绘制各自的区域就能绘制出一个带颜色渐变的TextView

2,然后外部再包装一层LinearLayout,水平排放每个tab,再监听Viewpage的滑动,根据滑动百分比来改变TextView的选中以及未选中区域的大小三,代码实现

三,难点

1,绘制渐变色的TextView其实最重要的还是计算基线的位置,基线位置计算出来,那么就能调用drawText()方法去绘制我们的文本了,在这里我也是参考某大佬的思想:基线计算方式

四,代码实现渐变TextView

/*** create by lijianhui* on 2022-7-21* <p>* description: 渐变色TextView*/
@RequiresApi(Build.VERSION_CODES.Q)
class CustomTextView : AppCompatTextView {/*** 未选中画笔*/private var mUnSelectPaint: Paint? = null/*** 选中画笔*/private var mSelectPaint: Paint? = null/*** 滑动进度百分比*/var mScrollProcess = 0f/*** 是否左边滑动*/var mScrollToLeft = true/*** 文字缩放比例*/var mTextScale = 0.7f/*** 选中颜色以及未选中颜色*/private var mSelectColor = Color.parseColor("#8966FF")private var mUnSelectColor = Color.parseColor("#DBC0FF")constructor(context: Context) : this(context, null)constructor(context: Context, attributeSet: AttributeSet?) : this(context, attributeSet, 0)constructor(context: Context, attributeSet: AttributeSet?, defStyleAttr: Int) : super(context,attributeSet,defStyleAttr) {//初始化画笔mUnSelectPaint = Paint()mUnSelectPaint?.apply {color = mUnSelectColortextSize = this@CustomTextView.textSizeisAntiAlias = trueisDither = true}mSelectPaint = Paint()mSelectPaint?.apply {color = mSelectColortextSize = this@CustomTextView.textSizeisAntiAlias = trueisDither = true}}/*** 绘制内容*/override fun onDraw(canvas: Canvas?) {val x = width * mScrollProcessif (mScrollToLeft) {drawText(canvas!!, mUnSelectPaint!!, x, width.toFloat())drawText(canvas!!, mSelectPaint!!, 0f, x)} else {drawText(canvas!!, mUnSelectPaint!!, 0f, width - x)drawText(canvas!!, mSelectPaint!!, width - x, width.toFloat())}}/*** 绘制文字*/private fun drawText(canvas: Canvas, paint: Paint, startX: Float, endX: Float) {paint.textSize = textSize * mTextScale//保存画布,剪切画布(设置画布显示区域)canvas.save()canvas.clipRect(startX, 0f, endX, height.toFloat())//获取文字矩形区域var bounds = Rect()paint.getTextBounds(text, 0, text.length, bounds)//获取文字的度量指标val fontMetrics = paint.fontMetrics//计算基线到中心点位置val dy = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom//计算基线val baseLine = height / 2 + dy//绘制文字canvas.drawText(text.toString(),(width / 2 - bounds.width() / 2).toFloat(),baseLine,paint)canvas.restore()}/*** 设置选中 未选中颜色*/fun setColor(selectColor: Int, unSelectColor: Int) {mSelectColor = selectColormUnSelectColor = unSelectColormSelectPaint?.color = selectColormUnSelectPaint?.color = unSelectColorinvalidate()}
}

1,在构造方法中初始化两支画笔,分别用于绘制未选中区域和选中区域

2,在onDraw()方法中根据滑动百分计算出绘制区域的宽度

3,判断滑动方向

4,开始绘制文本

4.1,设置画笔的文字大小(文字大小 * 缩放比例)

4.2,保存画布,并根据计算出来的绘制区域的开始坐标和结束坐标剪切画布,这是整个绘制核心,一旦剪切等下调用darwText()方法就只会绘制剪切的这部分

4.3,获取文字矩形区域,通过调用paint.getTextBounds()这个方法就能拿到我们绘制文本的区域

4.4,获取文字的度量指标,计算出基线的位置

4.5,调用画布的drawText()去绘制我们的文本

5,效果如下,对算法不理解的需要自行去搜索getTextBounds(),getFontMetrics()这两个方法的作用及其属性变量的作用,到这里,一个渐变色的TextView就出来了,最后容我埋下一个bug

五,代码实现指示器

/*** create by lijianhui* on 2022-7-21* <p>* description: 自定义颜色渐变 文字缩放指示器*/
@RequiresApi(Build.VERSION_CODES.Q)
class MyIndicator : LinearLayout, ViewPager.OnPageChangeListener {var mTextScale = 0.7fconstructor(context: Context) : this(context, null)constructor(context: Context, attributeSet: AttributeSet?) : this(context, attributeSet, 0)constructor(context: Context, attributeSet: AttributeSet?, defStyleAttr: Int) : super(context,attributeSet,defStyleAttr)/*** 添加多个tab*/fun addTabs(texts: List<String>) {texts.forEach {addTab(it)}//选中第一个val customTextView = getChildAt(0) as CustomTextViewcustomTextView.mScrollToLeft = falsecustomTextView.mScrollProcess = 1fcustomTextView.mTextScale = 1fcustomTextView.invalidate()}/*** 添加tab*/fun addTab(text: String) {val layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT)layoutParams.weight = 1fval customTextView = CustomTextView(context)customTextView.textSize = 21fcustomTextView.gravity = Gravity.CENTERcustomTextView.text = textcustomTextView.mScrollProcess = 0fcustomTextView.mTextScale = 0.7fcustomTextView.layoutParams = layoutParamsaddView(customTextView)}/*** 关联ViewPage*/fun relationViewPage(viewPage: ViewPager) {viewPage.addOnPageChangeListener(this)}/*** 滑动回调*/override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {if (positionOffset > 0) {val tabView = getChildAt(position) as CustomTextViewtabView.mScrollToLeft = falsetabView.mScrollProcess = 1 - positionOffsettabView.mTextScale = if ((1 - positionOffset) > mTextScale) 1 - positionOffset else mTextScaletabView.invalidate()val rightTabView = getChildAt(position + 1) as CustomTextViewrightTabView.mScrollToLeft = truerightTabView.mScrollProcess = positionOffsetrightTabView.mTextScale = if (positionOffset > mTextScale) positionOffset else mTextScalerightTabView.invalidate()}}/*** 选中某个item回调*/override fun onPageSelected(position: Int) {}/*** 滑动状态改变回调*/override fun onPageScrollStateChanged(state: Int) {}
}

1,循环添加多个颜色渐变的CustomTextView,默认选中第一个

2,关联ViewPage,给ViewPage设置一个OnPageChangeListener监听器,监听其滑动距离,根据滑动百分比计算出CustomTextView的滑动比例,CustomTextView的文字缩放比例

3,效果如下,如有不理解的版代码过去自行改改参数就理解其中奥秘了,动起来

自定义炫酷效果ViewPage指示器相关推荐

  1. 自定义炫酷powershell

    自定义炫酷powershell(美化) linux上的bash和zsh之类的命令行终端炫酷无比. window上的cmd和powershell丑的不忍直视. 很久之前不知参考谁的一篇文章自定义了一下, ...

  2. 超酷的计步器APP(一)——炫酷功能实现,自定义水波纹特效、自定义炫酷开始按钮、属性动画的综合体验

    超酷的计步器APP(一)--炫酷功能实现,自定义水波纹特效.自定义炫酷开始按钮.属性动画的综合体验 好久没写博客了,没给大家分享技术了,真是有些惭愧.这段时间我在找工作,今年Android的行情也不怎 ...

  3. Android炫酷效果集锦

    安卓开发中非常炫的效果集合 这几天开发的时候,想做一些好看而且酷炫的特效,于是又开始从网上收集各种特效资源.下面给大家一些我喜欢的把,附代码,喜欢的看源代码,然后加到自己项目去把!! 一个开源项目网站 ...

  4. android炫酷效果集合

    这几天开发的时候,想做一些好看而且酷炫的特效,于是又开始从网上收集各种特效资源.下面给大家一些我喜欢的把,附代码,喜欢的看源代码,然后加到自己项目去把!! 一个开源项目网站有很多炫酷效果  http: ...

  5. Android开发——自定义炫酷PickerView惯性滚动魔改

    Android开发--自定义炫酷PickerView快速滚动魔改 最近由于课内压力的增加和安卓课设项目,故没有怎么刷acm题,基本上学校要训练也就去水一波,程序设计相关内容也鸽了. 由于从来没有做过开 ...

  6. html border阴影效果_一篇文章教会你使用html+css3制作炫酷效果

    [一.项目背景] 在浏览一些网站的时候,经常会看到很多的炫酷的效果去装饰页面,使它看起来更高端大气一些.比如,艺龙就采用了图片上加载文字,点击图片使把对应的图片放大,使用户清晰,直观的看到内容.这种效 ...

  7. 仿网易/QQ空间视频列表滚动连播炫酷效果

    代码地址如下: http://www.demodashi.com/demo/11201.html 一.准备工作 AndroidStudio 开发环境 需要下载七牛的开源播放器SDK 本例子实现了仿网易 ...

  8. 第七章 实现炫酷效果—图像和动画(1)

    第七章实现炫酷效果图像和动画 1 Android的几种常用图像类型 2 图片的基础Bitmap位图 21如何获取位图资源 22如果获取位图的信息 23 位图的显示与变换 第七章实现炫酷效果-图像和动画 ...

  9. 黑客帝国中代码雨如何实现?用 canvas 轻松实现代码雨炫酷效果!

    目录 1 效果 2 用到的知识点 2.1  什么是 canvas标签? 2.1.1 创建一个画布(Canvas) 2.1.2 使用 JavaScript 来绘制图像 2.1.3 Canvas 坐标 2 ...

  10. Android探索之旅(第十四篇)Android中实现炫酷效果的Demo(持续收录中......)

    RangeSeekBar Android简单实现订单模块类APP的物流详情页 Android开发中阴影效果的实现 Android 炫酷多重水波纹 MultiWaveHeader 利用Spannable ...

最新文章

  1. [watevrCTF 2019]Baby RLWE
  2. mysql主从复制周期_Mysql主从复制的实现
  3. 互联网上最可怕的女人
  4. python字典嵌套循环_python使用for循环更新嵌套字典值
  5. 推荐给java新手的JAVA零基础入门书籍
  6. [PHPCMS]精美大气自适应资源模板下载网站源码
  7. centos安装office及PDF阅读器
  8. 初识Python必看基础知识~ 续(6)九层之台,起于垒土,肝肝肝~
  9. 这有清理C盘空间的妙招,学会了就不怕内存满了
  10. error Type referred to is not an annotation type:
  11. iPhone12打开webview闪退或者白屏
  12. heka 0.11.0源码分析--Elasticsearch OutPut插件
  13. 交叉编译arm版linaro-1.13.1-4.7-2013.03
  14. 软件定义闪存: SSD加速企业数据中心变革
  15. 上海的二手房价有所下跌,现在你们的工资够买间厕所了吗?Python帮你分析上海的二手房价
  16. android加载GIF动画
  17. MySQL(学生表、教师表、课程表、成绩表)多表查询
  18. PM创造营——从粗放化管理转型到精细化管理,PMO如何将流程正规化落地企业?
  19. Linux车载导航程序,基于嵌入式LINUX的车载导航系统设计
  20. 实验室环境下测试千兆入侵检测系统(转)

热门文章

  1. Echarts制作泊松分布图,并加临界线
  2. XJOI一级六段题解(g++,即C++),也可视作C++算法竞赛教程
  3. 计算机办公软件海报,word知识面制作一个图文并茂的宣传海报
  4. 分布式文件存储SeaweedFS试用对比总结
  5. [解决方法]shc -f xxx.sh shc: invalid first line in script
  6. GTP 协议常用术语
  7. 三维点云处理(深度学习方法)综述
  8. JavaScript 视频、图片转成Base64格式
  9. 双足机器人的稳定性判据_仿人双足机器人步态规划——零力矩点(ZMP)
  10. IOS逆向-静态分析