本文主要是介绍Android SwipeRefreshLayout实现工作原理.,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
首先这个工具类是由V4包提供的,翻看里面的源码发现,原来这个工具视图[主要探讨视图]是通过自己创建了一个圆形VIew,并在圆形View里面添加了一个旋转的进度Drawable,当然旋转的并不是一个控件,仅仅是一个资源.并通过圆形View去设置了该Drawable,并将圆形图片添加到了SwieRefresh控件上.具体源码如下,通过该源码你可以找到MaterialProgressDrawable,自己手动实现一些进度,大致看了一下算法,还不错,如果你想依赖原生的,你就可以自己创建一个控件去设置这个背景.
mCircleView = new CircleImageView(getContext(), CIRCLE_BG_LIGHT, CIRCLE_DIAMETER/2);mProgress = new MaterialProgressDrawable(getContext(), this);mProgress.setBackgroundColor(CIRCLE_BG_LIGHT);mCircleView.setImageDrawable(mProgress);//设置圆形进度资源mCircleView.setVisibility(View.GONE);addView(mCircleView);
然后
MaterialProgressDrawable提供一些方便的api,
<pre name="code" class="java">setAlpha(float); // 设置渐变
showArrow(boolean);// 设置箭头
setStartEndTrim(float,float); // 开始和结束的长度这里默认是0.8f,参考源码:mProgress.setStartEndTrim(0f, Math.min(MAX_PROGRESS_ANGLE, strokeStart));
setArrowScale(float); //缩放箭头
/*关键的旋转代码*/
<pre name="code" class="java">float rotation = (-0.25f + .4f * adjustedPercent + tensionPercent * 2) * .5f; // ACTION_MOVE的时候计算的一个旋转值,然后给该设置,当然你也可以自己定义.
mProgress.setProgressRotation(rotation);// 设置旋转值.
mProgress.start();//开始旋转
mProgress.stop(); // 结束旋转.
下面是MaterialProcessDrawable部分算法源码:
// The minProgressArc is calculated from 0 to create an// angle that// matches the stroke width.final float minProgressArc = (float) Math.toRadians(ring.getStrokeWidth() / (2 * Math.PI * ring.getCenterRadius()));final float startingEndTrim = ring.getStartingEndTrim();final float startingTrim = ring.getStartingStartTrim();final float startingRotation = ring.getStartingRotation();// Offset the minProgressArc to where the endTrim is// located.final float minArc = MAX_PROGRESS_ARC - minProgressArc;final float endTrim = startingEndTrim + (minArc* START_CURVE_INTERPOLATOR.getInterpolation(interpolatedTime));ring.setEndTrim(endTrim);final float startTrim = startingTrim + (MAX_PROGRESS_ARC* END_CURVE_INTERPOLATOR.getInterpolation(interpolatedTime));ring.setStartTrim(startTrim);final float rotation = startingRotation + (0.25f * interpolatedTime);ring.setRotation(rotation);float groupRotation = ((720.0f / NUM_POINTS) * interpolatedTime)+ (720.0f * (mRotationCount / NUM_POINTS));setRotation(groupRotation);//设置旋转值
/***画箭头**/
private void drawTriangle(Canvas c, float startAngle, float sweepAngle, Rect bounds) {if (mShowArrow) {if (mArrow == null) {mArrow = new android.graphics.Path();mArrow.setFillType(android.graphics.Path.FillType.EVEN_ODD);} else {mArrow.reset();}// Adjust the position of the triangle so that it is inset as// much as the arc, but also centered on the arc.float inset = (int) mStrokeInset / 2 * mArrowScale;float x = (float) (mRingCenterRadius * Math.cos(0) + bounds.exactCenterX());float y = (float) (mRingCenterRadius * Math.sin(0) + bounds.exactCenterY());// Update the path each time. This works around an issue in SKIA// where concatenating a rotation matrix to a scale matrix// ignored a starting negative rotation. This appears to have// been fixed as of API 21.mArrow.moveTo(0, 0);mArrow.lineTo(mArrowWidth * mArrowScale, 0);mArrow.lineTo((mArrowWidth * mArrowScale / 2), (mArrowHeight* mArrowScale));mArrow.offset(x - inset, y);mArrow.close();// draw a trianglemArrowPaint.setColor(mColors[mColorIndex]);c.rotate(startAngle + sweepAngle - ARROW_OFFSET_ANGLE, bounds.exactCenterX(),bounds.exactCenterY());c.drawPath(mArrow, mArrowPaint);}}
这儿主要是画进度:
/*** Draw the progress spinner*/public void draw(Canvas c, Rect bounds) {final RectF arcBounds = mTempBounds;arcBounds.set(bounds);arcBounds.inset(mStrokeInset, mStrokeInset);final float startAngle = (mStartTrim + mRotation) * 360;final float endAngle = (mEndTrim + mRotation) * 360;float sweepAngle = endAngle - startAngle;mPaint.setColor(mColors[mColorIndex]);c.drawArc(arcBounds, startAngle, sweepAngle, false, mPaint);drawTriangle(c, startAngle, sweepAngle, bounds);if (mAlpha < 255) {mCirclePaint.setColor(mBackgroundColor);mCirclePaint.setAlpha(255 - mAlpha);c.drawCircle(bounds.exactCenterX(), bounds.exactCenterY(), bounds.width() / 2,mCirclePaint);}}
下面是我自己定义的CircleView,算法如下.:
mRefreshStart += mIsStart ? 3 : 10;//计算距离mRefreshStop += mIsStart ? 10 : 3;mRefreshStart = mRefreshStart % 360;//还原位置mRefreshStop = mRefreshStop % 360;int swipe = mRefreshStop - mRefreshStart;swipe = swipe < 0 ? swipe + 360 : swipe; //计算扫过的角度.canvas.drawArc(rectF,mRefreshStart, swipe, false, mOutPaint);//画圆弧.if (swipe >= 330) {//恢复加速mIsStart = false;} else if (swipe <= 10) {//开始加速mIsStart = true;}
GitHub地址:https://github.com/q422013/CircleView
这篇关于Android SwipeRefreshLayout实现工作原理.的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!