京东客户端的轮播文字效果:
本次要实现的只是后面滚动的文字(前面的用ImageView或者TextView实现即可),看一下实现的效果
实现思路
上图只是一个大概的思路,要实现还需要完善更多的细节,下面会一步步的来实现这个效果:
1.封装数据源:从图上可以看到,轮播的文字是分为两个部分的,暂且把它们分别叫做前缀和内容,而且实际的使用过程中点击轮播图肯定是需要跳转页面的,而且大部分应该是WebView,不妨我们就设置点击时候需要获取的内容就是一个链接,那么数据源的结构就很明了了
创建ADEnity
类并完善一些基本的方法,代码如下
public class ADEnity { private String mFront ; //前面的文字 private String mBack ; //后面的文字 private String mUrl ;//包含的链接 public ADEnity(String mFront, String mBack,String mUrl) { this.mFront = mFront; this.mBack = mBack; this.mUrl = mUrl; } public String getmUrl() { return mUrl; } public void setmUrl(String mUrl) { this.mUrl = mUrl; } public String getmFront() { return mFront; } public void setmFront(String mFront) { this.mFront = mFront; } public String getmBack() { return mBack; } public void setmBack(String mBack) { this.mBack = mBack; } }
2.接下来应该是定制这个自定义View了,首先理一下思路,看一个构造图
实现这个自定义View的所有参数都在上表列出了,大部分参数很容易理解,个别参数加进去是很有必要的,比如说是否初始化进入文字的纵坐标,文字是否在移动中这两个参数,之后的内容会详细的叙述一下.
在动手绘制之前还得需要知道一点基础的知识,就是关于绘制文字的方法,里面有很多细节需要处理
首先是画布绘制文字的方法:
返回值 | 方法 | 描述 |
---|---|---|
void | drawText(String text, float x, float y, Paint paint) | Draw the text, with origin at (x,y), using the specified paint. |
void | drawText(CharSequence text, int start, int end, float x, float y, Paint paint) | Draw the specified range of text, specified by start/end, with its origin at (x,y), in the specified Paint. |
void | drawText(char[] text, int index, int count, float x, float y, Paint paint) | Draw the text, with origin at (x,y), using the specified paint. |
void | drawText(String text, int start, int end, float x, float y, Paint paint) | Draw the text, with origin at (x,y), using the specified paint. |
方法都比较好理解,绘制指定字符串(可以指定范围)在坐标( x , y )
处,但是其中的x,y
并不是我们所理解的应该是文字左上角的坐标点.其中的x坐标是根据Paint
的属性可变换的,默认的x是文字的左边坐标,如果Paint
设置了paint.setTextAlign(Paint.Align.CENTER)
;那就是字符的中心位置.Y
坐标是文字的baseline
的y
坐标.
关于绘制文字的baseline
:
用图来说话吧
图中蓝色的线即为baseline
,可以看出他既不是顶部坐标也不是底部坐标,那么当我们绘制文字的时候肯定是希望能把文字绘制在正中间.这时候就要引入paint.getTextBound()
方法了
getTextBounds(String text, int start, int end, Rect bounds)
,传入一个Rect
对象,调用此方法之后则会填充这个rect对象,而填充的内容就是所绘制的文字相对于baseline
的偏移坐标,将这个Rect加上baseline
的坐标,绘制后是这样的:
但其实他的值只是(2,-25,76,3)
,是相对于baseline的位置,画个图会比较好理解
<h3 id="那么要将文字绘制在中间那么实际绘制baseline的坐标应该是组件的中心加上文字中心即图中框的中间坐标相对于baseline的偏移值">那么要将文字绘制在中间,那么实际绘制baseline的坐标应该是组件的中心,加上文字中心(即图中框的中间坐标)相对于baseline的偏移值
这张图中应该会好理解实际绘制文字的坐标与组件中心坐标的关系.关于偏移值的计算,按常规的几何计算方法,应该是组件的中心坐标+偏移值的绝对值==baseline坐标(即实际绘制的坐标)
,但是由于框的坐标值都是相对于baseline
来计算的,top
为负值,botton
为正值,那么这个偏移值就可以直接用(top+bottom)/2
来表示,没看懂的同学可以画个草图,用top=-25
,bottom=3
来算一下,看是否结果是一致的.
经过上面的理解,那我们来绘制正确绘制文字的方法也就确定了
已获得组件的高度int mHeight
, 文字外框Rect bound
的情况下
绘制文字在正中间
mHeight / 2 - (bound.top + bound.bottom) / 2 //在纵坐标为mY的地方绘制文字 //计算方式 //mheight /2 = mY + (bound.top + bound.bottom) / 2 ;
文字滚动到最高点
mY == 0 - bound.bottom //在纵坐标为mY的地方绘制,此时文字刚好移动到最高点 //计算方式 //mY + bound.bottom = 0 ;
文字滚动到最低点,刚好滚出组件
mY = mHeight - indexBound.top; //在纵坐标为mY的地方绘制,此时文字刚好移动到最高点 //计算方式 //mY + bo