如何应对Android面试官->文字中心绘制和颜色渐变,实战头条炫酷ViewPager指示器

Viewpager2+Fragment+指示器 【代码】Viewpager2+Fragment+指示器。 阅读详情

前言

本章要实现的效果

自定义TextView文字绘制

我们在进行文字的自定义绘制的时候,通过不会通过 setText 的方式,而是重写 onDraw 方法,通过 Canvas 的 drawText 方法来实现,整体实现方式如下:

public class CustomTextView extends AppCompatTextView {    
    public CustomTextView(@NonNull Context context) {        
        super(context);    
    }    
    public CustomTextView(@NonNull Context context, @Nullable AttributeSet attrs) {        
        super(context, attrs);    
    }    
    public CustomTextView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        
        super(context, attrs, defStyleAttr);    
    }    
    @Override    
    protected void onDraw(Canvas canvas) {        
        super.onDraw(canvas);        
        Paint paint = new Paint();        
        canvas.drawText("我是老A", 0, 0, paint);    
    }
}

我们运行看下效果:

运行,并没有在屏幕上看到『我是老A』这几个字,这是为什么呢?我们来一探究竟

我们来看一下 drawText 的参数注释:

float y,是 text 的 baseline,这个 baseline 是什么鬼呢?

baseline

上图中的的那条红线,就是 baseline;大部分文字都以这条线为基准线,保证文字的对齐;而文字绘制的起始点,就是第一个文字的左下角,也就是下图剪头指的位置

y值 如果设置成0,文字其实就跑到屏幕外面了,所以我们的 y 值不能为0,我们修改下 y 值,然后看下效果:

可以看到 『我是老A』文字绘制了出来;因为没有设置文字的大小,所以看着会比较小;

也就是说:无论什么文字,Android 系统都会让其在某一条线上对齐,而这条对齐的线,就是 baseline,也叫做基准线;

有人可能会说了,为什么不把『我是老A』绘制到屏幕X轴中间位置,这样方便看,好的,那我们把这几个字绘制到屏幕的中间位置,为了便于看到中间位置,我们现在屏幕中心画一条竖线

private void drawCenterLineX(Canvas canvas) {    
    paint.setStyle(Paint.Style.FILL);    
    paint.setColor(Color.RED);    
    paint.setStrokeWidth(3);    
    canvas.drawLine(getWidth() / 2,0, getWidth()/2, getHeight(), paint);
}

我们在屏幕 X 轴上画了一条竖线;然后我们把 文字绘制到 X 轴中心位置

canvas.drawText("我是老A", getWidth() / 2, 200, paint);

运行看下效果:

咦咦咦,好像和我们期望的不一样,整体文字偏右了。。。那么怎么解决呢?我们需要设置文字的对齐方式

paint.setTextAlign(Paint.Align.CENTER);
canvas.drawText("我是老A", getWidth() / 2, 200, paint);

我们在编译运行看下效果:

这次文字不是从中心线的左侧开始绘制了;也就是说,如果我们不设置 TextAlign,那么默认的 TextAlign 是从左边开始;

我们现在是 X 轴的中心位置,那么如何绘制到 Y 轴的中心位置呢?我们先来画一条 Y 轴中心线

private void drawCenterLineY(Canvas canvas) {    
    paint.setStyle(Paint.Style.FILL);    
    paint.setColor(Color.RED);    
    paint.setStrokeWidth(3);    
    canvas.drawLine(0,getHeight() / 2, getWidth(), getHeight() / 2, paint);
}

那么,我们如何把文字绘制到中心位置呢?可能大家会说 Y 值直接除以 2,好,我们试一下

paint.setTextAlign(Paint.Align.CENTER);
canvas.drawText("我是老A", getWidth() / 2, getHeight() / 2, paint);

运行看下效果:

看起来,还是没有达到我们期望效果,希望文字在Y轴方向上平分,那么我们需要知道文字的高度才能进行向下绘制;那么文字的高度如何计算呢?

文字高度计算

我们需要使用 FontMetrics 来进行文字的高度测量,我们点进去看下这个类的实现:

这几个值,正好对应的就是下图的这几个值

那么文字的高度具体怎么计算呢?本质就是 ascent + descent 的值,但是根据 Android 坐标系来看 X 轴是右正左负,Y 轴是下正上负,也就是说根据基准线,我们的 ascent 值是 负值,descent 是正值,所以文字的高度最终的计算方式应是 descent - ascent 的值

所以 Y 值应该是 getHeight()/2 + ((fontMetircs.descent - fontMetircs.descent) / 2)

canvas.drawText("我是老A", getWidth() / 2, 
    getHeight() / 2 + ((fontMetrics.descent - fontMetrics.ascent)/2), 
    paint);

我们运行看下效果:

咦,还是不对呀,文字又偏下了,这是为什么呢?

文字绘制的(0, 0)点,是基于基准线来绘制的,也就是文字的左下角,如果我们用文字高度的一半的话,Y 轴的值就是偏大的,因为基准线的位置没有在文字高度的一半,所以需要减去一部分高度,这个减去的高度就是 descent;

canvas.drawText("我是老A", getWidth() / 2, 
    getHeight() / 2 + ((fontMetrics.descent - fontMetrics.ascent)/2) - fontMetrics.descent, 
    paint);

运行看下效果:

可以看到,这次我们的文字 绘制到了中心位置!

接下来,可能有人会问了,不用 TextAlign 可以将文字绘制到 X 轴中心位置吗?答案是可以的,我们只需要计算出文字的宽度,然后用屏幕宽度的一半减去文字宽度的一半,就可以算出起始位置;那么文字的宽度应该如何计算呢?

文字宽度的计算

使用 Paint 的 measureText 方法来获取文字的宽度,我们将 TextAlign 注释掉

Paint.FontMetrics fontMetrics = paint.getFontMetrics();
// paint.setTextAlign(Paint.Align.CENTER);
float width = paint.measureText("我是老A");
canvas.drawText("我是老A", getWidth() / 2 - width / 2 , 
    getHeight() / 2 + ((fontMetrics.descent - fontMetrics.ascent)/2) - fontMetrics.descent, 
    paint);

运行看下效果:

依然是中心位置;

自定义TextView颜色渐变

我们的文字绘制的时候,是不可能只绘制一半的,那么我们就需要对画布进行裁剪,而 canvas 也给我们提供了一系列的 API 来进行画布的裁切;

也就是说,我们对画布进行裁剪,裁剪之后,能绘制多少就会绘制多少,看个例子:

private void drawText(Canvas canvas) {    
    canvas.save();    
    paint.setTextSize(40);    
    Paint.FontMetrics fontMetrics = paint.getFontMetrics();    
    float width = paint.measureText("我是老A");    
    float baseLine = getHeight() / 2 + ((fontMetrics.descent - fontMetrics.ascent) / 2) - fontMetrics.descent;    
    float x = getWidth() / 2 - width / 2;    
    Rect rect = new Rect((int) x, 0, 330, getHeight());    
    canvas.clipRect(rect);    
    canvas.drawText("我是老A", x,            
            baseLine,            
            paint);    
    canvas.restore();
}

运行看下效果:

裁剪的画布只能够把『我』字绘制出来;

如果我们想实现文字的渐变,那么我们就可以用两层画布,一层是黑色,一层是红色,然后我们计算每一个字在整个文字占的百分比,从而设置 Rect 的右边界的值;

private void drawTextBlack(Canvas canvas) {    
    paint.setTextSize(40);    
    paint.setColor(Color.BLACK);    
    Paint.FontMetrics fontMetrics = paint.getFontMetrics();    
    float width = paint.measureText("我是老A");    
    float baseLine = getHeight() / 2 + ((fontMetrics.descent - fontMetrics.ascent) / 2) - fontMetrics.descent;    
    float x = getWidth() / 2 - width / 2;    
    canvas.drawText("我是老A", x,            
        baseLine,            
        paint);
}
private void drawTextRed(Canvas canvas) {    
    canvas.save();    
    paint.setTextSize(40);    
    Paint.FontMetrics fontMetrics = paint.getFontMetrics();    
    float width = paint.measureText("我是老A");    
    float baseLine = getHeight() / 2 + ((fontMetrics.descent - fontMetrics.ascent) / 2) - fontMetrics.descent;    
    float x = getWidth() / 2 - width / 2;    
    float right = x + width*mPercent;    
    Rect rect = new Rect((int) x, 0, (int) right, getHeight());    
    canvas.clipRect(rect);    
    canvas.drawText("我是老A", x,            
        baseLine,            
        paint);    
    canvas.restore();
}

我们需要动态的改变 mPercent 的值,可以通过属性动画,也可以通过 ViewPager 的手势滑动,我们先用属性动画来看下效果;

ObjectAnimator.ofFloat(view, "percent", 0f, 1f).setDuration(5000).start()

我们运行看下效果:

我们实现了文字的渐变效果;

ViewPager 的滑动监听,可以通过 onPageScrolled 回调设置

mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {    
    @Override    
    public void onPageSelected(int position) {    
    }    
    @Override    
    public void onPageScrolled(int position, float positionOffset,                               
            int positionOffsetPixels) {        
        if (positionOffset > 0) {            
            CustomTextView left = mTabs.get(position);            
            CustomTextView right = mTabs.get(position + 1);            
            left.setDirection(ColorChangeTextView1.DIRECTION_RIGHT);            
            right.setDirection(ColorChangeTextView1.DIRECTION_LEFT);            
            Log.v(TAG, positionOffset + "");            
            left.setProgress(1 - positionOffset);            
            right.setProgress(positionOffset);        
        }    
    }    
    @Override    
    public void onPageScrollStateChanged(int state) {    
    }
});

运行,实现我们开头的效果;

简历润色

简历上可写:深度理解文字绘制原理,可实现炫酷的文字绘制效果;

下一章预告

玩转RV,使用RecyclerView实现吸顶效果;

欢迎三连

来都来了,点个关注,点个赞吧,你的支持是我最大的动力~~~

Android进阶之路 - TextView文本渐变 那天做需求的时候,遇到一个小功能,建立在前人栽树,后人乘凉的情况下,仅用片刻就写完了;说来惭愧,我以前并未写过文本渐变的需求,脑中也仅有一个shape渐变带来的大概思路,回头来看想着学习一下这款自定义控件的内部实现,很多时候通过阅读原作者源码,总能为我们带来一些思考 阅读详情

相关推荐

自定义Android ViewPager控件实现指示器

在init()方法中,我们通过LayoutInflater加载了一个布局文件(layout_indicator_viewpager.xml),其中包含了一个ViewPager和一个指示器容器(indicatorContainer)。在该布局文件中,我们使用了一个LinearLayout作为指示器容器,并设置了水平方向的排列方式。通过以上的代码和布局,我们可以在Android应用中使用IndicatorViewPager来实现滑动切换页面,并在底部显示相应的指示器,用于指示当前页面的位置。

2301_79326588的博客 721

[Android开发]渐变色TextView,渐变色粗边TextView,支持不同角度渐变色

[Android开发]渐变色TextView,渐变色粗边TextView,支持不同角度渐变色

u013077428的博客 5503

Android ViewPageIndicator组件详解与实践

本文还有配套的精品资源,点击获取 简介:在Android开发中,ViewPageIndicator组件常与ViewPager结合使用,以实现页面切换时底部指示器的视觉效果。该组件支持多种自定义选项,包括不同样式和监听事件。开发者可以通过添加依赖、布局文件配置、适配器创建、数据设置、样式调整和事件监听等步骤实现一个视觉吸引力强且功能丰富的页面指示器。 1. View...

weixin_31459297的博客 905

安卓实现随Viewpager滑动而滑动的指示器小圆点

此前在网上看到好多大神写的指示器,也有带平移效果的,但是都不是怎么满意,菜鸟的我今天在这里贡献一下利用shape和自定义View实现的Viewpager指示器,并且还可以多种自定义样式哦,欢迎大家共同来探讨和评论,代码还有很多优化及修改的地方欢迎大家发表意见 下面展示一下效果: 有需要的小伙伴可以在下方留言这里将发送demo,近期可能会更新上码云,需要码云链接的可以在下方评论,话不多说下面展示核...

Android爬坑牛奶糖的博客 2682

K2P padavan固件下宽带与IPTV融合

举例说下,假如你的IPTV是拨号的,IPTV端口直接连到笔记本电脑的网口,IP是自动分配的情况下,在VLC里面是可以直接播放“rtp://239.XXX.XXX.XXX:XXXX”的,即使IPTV是DHCP模式,按道理也是可以播放的。家里很少看电视,基本上就是看看春晚,然后平时老人在家没事看看,所以就把广电的机顶盒停掉了,换了一个N1的盒子刷了CoreELEC系统,既可以通过m3u8文件看网络电视,也可以看本地的多媒体,很方便,完全满足了自己的需求。在上图的第三步中,端口设置成大于1024的端口即可。

aplsc的专栏 63万+

RML2016.10a (CNN、LSTM、CNN-LSTM、CNN-LSTM-Multi-head-attention, TensorFlow)

RML2016.10a (CNN、LSTM、CNN-LSTM、CNN-LSTM-Multi-head-attention, TensorFlow) 包含所有数据和代码,支持一键运行(jupyter)

qq_40999533的博客 1482

面试题kkk

这篇文章摘要主要涵盖了Android开发中的核心知识点和技术难点,包括数据结构、Java与Kotlin语言特性、多线程与并发、内存管理、安卓组件与UI、IPC通信、数据库、多媒体处理、设计模式、性能优化、跨端开发等多个方面。文章详细解析了常见数据结构的使用与实现、JVM机制、内存泄漏分析与解决方案、Activity生命周期、事件分发机制、Handler原理、音视频处理、设计模式应用等核心内容,并提供了实际项目中的技术卡点与解决方案。此外,还涉及了性能优化策略、跨端开发差异、技术方案设计思路以及Git常用命令

mix39的博客 929

山东大学软件学院计算机组成原理课程设计实验二

文章目录一、实验时间二、实验内容1.设计异步模16加1计数器2.设计4位移位器3.超前进位16位ALU的设计 一、实验时间 2021年4月1日星期四,第五周 二、实验内容 1.设计异步模16加1计数器 基本功能:使用D触发器(dff元件)和异或门构建从0开始计数的模16加1计数器 对应的电路图(这里已经实现了预置初值的功能) 拓展功能: (1)实现模256加1计数器 (2)实现计数器预置初值的功能 这里复用了上面的模16加1计数器 这里异步触发器预置初值的功能是这样实现的: (1)首先将CLR端调为0,

叶卡捷琳堡的博客 5247

android 文本渐变显示

Android开发过程中,对TextView会用得非常多,字体颜色渐变或增加很多色彩.

lizhong 3284

避坑指南:英飞凌TC3XX的MCMCAN初始化常见错误及解决方法

本文针对英飞凌TC3XX系列MCU的MCMCAN模块初始化难题,深入剖析了寄存器配置时序、总线监控模式误用、中断映射错误及Message RAM地址冲突四大常见陷阱。通过实战代码示例和诊断流程,提供了清晰的避坑指南和解决方案,帮助嵌入式开发者高效解决CAN FD通信故障,确保汽车电子与工业控制项目的稳定运行。

weixin_29193259的博客 244

Gromacs 模拟昆虫 P450 解毒酶与农药结合完整指南,仅供参考!

🏆 本文收录于《全栈Bug调优(实战版)》专栏,致力于分享我在项目实战过程中遇到的各类Bug及其原因,并提供切实有效的解决方案。无论你是初学者还是经验丰富的开发者,本文将为你指引出一条更高效的Bug修复之路,助你早日登顶,迈向财富自由的梦想🚀!同时,欢迎大家关注、收藏、订阅本专栏,更多精彩内容正在持续更新中。让我们一起进步,Up!Up!Up!    备注: 部分问题/难题源自互联网,经过精心筛选和整理,结合数位十多年大厂实战经验资深大佬经验总结所得,数条可行方案供所需之人参考。

**My Coding Family** 1239

设置TextView 渐变背景和字体渐变色

val spannable = SpannableString("文本内容")第二步:设置线性渐变,起始颜色和结束颜色。第一步:找到 TextView 的ID。第三步:设置textview的绘画阴影。第四步:设置textview。

21空间的博客 1350

利用AWVS进行反制

awvs 10.5下载 http://www.32r.com/soft/12986.html

渗透之路,攻防之间皆学问 6653

Android简单的ViewPager指示器

平常写项目在写介绍页,或者一些简单的轮播图的时候,总会需要搭配指示器来标明当前在什么位置.写法也比较多,刚好自己需要用到,以前用的一些方法,用起来需要配置好多东西,有些大材小用,所以来简单的实现一个.效果图如下:一、简单分析与代码实现因为比较简单,所以就简单的分析一下: 1)每一个指示器项有两种状态,普通状态和选中状态,所以需要准备两种状态的图片. 2)指示器的个数和ViewPager的页数要保

冷不冷的博客 8381

2、实时DSP编程技术及其应用

本文详细介绍了实时数字信号处理(DSP)技术及其应用,涵盖三种流行的浮点DSP处理器系列的特点、开发工具和优化方法。通过具体的应用实例,如语音压缩、音乐信号处理和雷达信号处理,展示了如何在实际项目中应用这些技术,帮助工程师提高系统的性能和可靠性。

cicd6pipeline的博客 838

SpringBoot项目搭建

SpringBoot项目搭建

私信可回答各种问题~ 1020

Android TCP传输自定义格式数据帧(1)

int value;}else{3.连接byte[]4.十六进制String > byte[]i < len;i++) {5.byte[] > 十六进制String。

2401_84544914的博客 943

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Android设置文字颜色渐变

项目中用到了很多文字颜色渐变的设计,因此做一下记录。属性颜色值,否则不会产生预期效果。

折翅鵬的博客 1962

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

炫酷ViewPager指示器效果(全面解析)

作者博客https://keep2iron.github.io/目录前言准备效果展示布局分析ViewPager的效果实现ViewPager布局设置ViewPager代码设置BeizerI...

陈宇明 512

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

android ViewPager 指示器 PageIndicator

一款 google写的 ViewPager 指示器 PageIndicator

lmjssjj的专栏 1640

ViewPagerIndicator: 为你的 Android 应用导航

在 Android 应用开发中,`ViewPager` 是一种非常流行的用于展示滑动视图的组件。然而,`ViewPager` 默认并不提供页面指示器(如小圆点或小方块),这就需要开发者自己实现。`ViewPagerIndicator` 是一个开源库,它为 `ViewPager` 提供了丰富的页面指示器效果,使得用户能够直观地看到当前页面的位置。本文将带你深入了解 `ViewPagerIndicator` 的核心特性、使用方法以及如何在 Android 应用中实现页面导航。

Unity打怪升级 1338

代码记录:textview文字多颜色渐变、imageview图片无限旋转

textview文字多颜色渐变LinearGradient、imageview图片无限旋转ObjectAnimator

西决的博客 266

给textView设置文字渐变色

一定要先设置shader,在设置字。如果先设置的字或者在xml里面设置的字,就需要设置完shader之后调用一下触发重新绘制的代码。4.最后一个参数为渐变的效果,我这里选择的就是从开始的颜色渐变到结束的颜色,这里不再赘述,感兴趣的可以去搜下各种渐变的效果。viewBinding.title这是一个textView。3.第5个参数为开始的颜色,第6个参数为结束的颜色。2.前4个参数为描述位置,我这里描述的是从上到下。从上到下x=x1y改变。从左到右x改变y=y1。......

lgz0921的博客 1697

MagicIndicator系列之一 —— 使用MagicIndicator打造千变万化的ViewPager指示器

说到 ViewPager 指示器,想必大家都不陌生,绝大部分应用中都有这个。使用频率非常之高。但系统对它的支持并不好,自带的 PagerTabStrip 和 PagerTitleStrip 太弱,很难满足需求。当然也有第三方框架诸如 Jake Wharton 大神的ViewPagerIndi...

chuanao8829的博客 626

android Textview颜色渐变

TextView mText = (TextView) findViewById(R.id.text); LinearGradient mLinearGradient = new LinearGradient(0, 0, 0, mText.getPaint().getTextSize(), Color.WHITE, Color.BLACK, Shader.TileMode.CLAM

leigo 1万+

自定义View-渐变TextView(重点:绘制文本)

自定义View-渐变TextView(重点:绘制文本)

璐璐的专栏 1279
上一篇: 如何应对Android面试官->事件分发冲突与解决方案大揭秘
下一篇: 如何应对Android面试官->我用RecyclerView实现了吸顶效果
老A说
博客等级 码龄14年 1181粉丝 85原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值