高仿QQ下拉刷新之LoadView
Posted FightSeeker
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高仿QQ下拉刷新之LoadView相关的知识,希望对你有一定的参考价值。
开始之前,先把效果图贴上,一睹为快,相似度还是蛮高的,嘿嘿!
此加载状态提示,我分为了四个部分来写,分别是:
(1)加载当中,LoadIngView
(2)加载之前,即用户下拉的状态,LoadPreView
(3)加载成功,LoadSuccessView
(4)控件组合,LoadView,也即是我们xml布局用到的
下面一一来介绍一下涉及到的主要核心代码:
1.关于LoadInngView的核心代码,主要思想是,通过改变十二条短线圆柱的颜色,实现加载的循环效果。
首先初始化颜色,代码如下
private void initColor()
colorEvaluator = new ArgbEvaluator();
colors = new int[count];
for(int i = 0;i < count;i++)
colors[i] = (int)colorEvaluator.evaluate(i*1.0f/(count-1),startColor,endColor);
很简单的一段代码,就是根据颜色插值器ArgbEvaluator,两种颜色,生成在startColor与endColor区间内的12中颜色
其次,就是初始化线段,代码如下
private void initLoadingLines()
loadingLines = new LoadingLine[count];
for(int i = 0;i <count;i++)
LoadingLine loadingLine = new LoadingLine();
loadingLine.drawColor = colors[i];
loadingLines[i] = loadingLine;
这段代码目的就是事先生成count条线段,并暂时初始化颜色。
再其次就是,初始化线段绘制的起始结束坐标,
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom)
float delayAngle = 360.0f / count;
LoadingLine loadingLine;
double value;
for(int i = 0;i < count;i++)
loadingLine = loadingLines[i];
value = startAngle * Math.PI / 180;
loadingLine.startX = (int)Math.round(radius * Math.cos(value));
loadingLine.startY = (int)Math.round(radius * Math.sin(value));
loadingLine.endX = (int)Math.round(exactlySize / 2.5f * Math.cos(value));
loadingLine.endY = (int)Math.round(exactlySize / 2.5f * Math.sin(value));
startAngle += delayAngle;
startAngle = 0;
这个就考验你的数学功力了,不说!
最后,颜色的改变,其实也就是实现循环效果的一部分,
private Runnable runnable = new Runnable()
@Override
public void run()
postInvalidate();
removeCallbacks(runnable);
setColor(startIndex % count);
startIndex++;
postDelayed(runnable,DELAY_DURATION);
;
/**
* 设置显示颜色
* @param index,线段颜色初始化位置
*/
private void setColor(int index)
int lineIndex;
for(int i = 0;i < count;i++)
lineIndex = index + i;
loadingLines[lineIndex >= count?lineIndex - count:lineIndex].drawColor = colors[i];
index说明一下,这个是显示颜色数组的第一个颜色,然后依次循环为每一个线段在赋值颜色。
2.LoadPreView:
这个其实没啥好说的,就是一些图形的绘制。难度点在于怎么绘制下拉的状态,正常的图形绘制肯定是不行,所以这里用到了二阶贝塞尔曲线的绘制,绘制Path生成如下:
/**
* 重置贝塞尔曲线
*/
private void resetBeaierPath()
/* 四个点 */
final float headerX1 = -mCurrentHeaderRadius;
final float headerX2 = mCurrentHeaderRadius;
final float headerY = 0;
final float footerX1 = -mCurrentFooterRadius;
final float footerX2 = mCurrentFooterRadius;
final float footerY = delaY;
/* 控制点 */
final float anchorX1 = headerX1 / anchorPercent;
float anchorY = delaY / anchorPercent;
anchorY = anchorY > exactlySize / 1.5f?exactlySize / 1.5f:anchorY;
final float anchorX2 = headerX2 / anchorPercent;
/* 画贝塞尔曲线 */
mPath.reset();
mPath.moveTo(headerX1, headerY);
mPath.quadTo(anchorX1, anchorY, footerX1, footerY);
mPath.lineTo(footerX2, footerY);
mPath.quadTo(anchorX2, anchorY, headerX2, headerY);
mPath.lineTo(headerX1, headerY);
其实就是6个点的确定,(headerX1,headerY),
(headerX2,headerY),(footerX1,footerY),(footerX2,footerY),(anchorX1,anchory),(anchorX2,anchorY),前面四个点做为固定点,是贝塞尔曲线闭合的4个点,后面两个是控制点。另外再说下,这个方法
private void resetValue(float percent)
this.anchorPercent = 1.0f + percent;
this.delaY = maxBezierLength * percent;
this.mCurrentFooterRadius = (1 - percent >= 0.25f? 1- percent:0.25f) * (exactlySize / 2.0f - ringWidth);
float p = 1.0f - percent / 3.0f;
this.arrowRadius = exactlySize / 4.5f * p;
this.triangleLength = applyDimension(TRIANGLE_LENGTH) * p;
this.arcWidth = applyDimension(INNER_ARC_WIDTH) * p;
this.mCurrentHeaderRadius = p * (exactlySize / 2.0f - ringWidth);
这是根据下拉的大小来实时更新各个参数的,能实现贝塞尔的下拉效果,这个参数的计算是必须的。
3.LoadSuccessView的绘制,这部分的绘制其实就是一个圆圈加对号以及文字的绘制,其中文字的绘制如下:
/**
* 绘制加载成功文字提示
* @param canvas
*/
private void drawText(Canvas canvas)
canvas.save();
Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
RectF targetRect = new RectF((padding + radius)*2,0,getWidth(),getHeight());
int baseLine = (int)((targetRect.bottom + targetRect.top - fontMetrics.bottom - fontMetrics.top) / 2);
canvas.translate((padding + radius)*2,baseLine);
canvas.drawText(TEXT,0,0,textPaint);
canvas.restore();
文字的绘制,其中确定基线是重要的,直接影响到你文字绘制的高度问题,基线的确定如代码所写。
4.LoadView,这部分更没啥,动态添加控件嘛,这个不会就去找度娘或者谷歌吧。具体的实现方式可以看代码,在这俺就不贴咧。
以上是关于高仿QQ下拉刷新之LoadView的主要内容,如果未能解决你的问题,请参考以下文章
Android 修改源码自定义SwipeRefreshLayout样式——高仿微信朋友圈下拉刷新