Android仿58同城Loading View
來自: http://blog.csdn.net//lcq5211314123/article/details/49101935
今天打開58同城App看到他們的網絡加載Loading做的很有新意,是一個三角形,圓形,正方形不同的運動并且切換,這個效果不說有多難,至少很有創意,就著手模仿了一下,先看下效果圖:
58的更加復雜,在形狀運動的過程還一直不停的旋轉,旋轉的坐標計算太復雜, 還沒有搞定,先把這個半成品開源出來。
思路:1.先畫一個靜態的形狀和下面的陰影。
2.通過ValueAnimator不停的改變縱坐標,在動畫的監聽中拿到 當前的坐標值,重新invalidate()此時的View。
3.在向下的動畫執行完畢后,更新Shape。然后讓動畫不停的運動即可。
package view;
/ @description 仿58加載View @author rzq @date 2015年10月10日 /
public class MyLoadingView extends View
{
/ 公共變量 /
private Context mContext;
private Resources mResource;
private Paint mPaint;
private Paint mOvalPaint;
/* /
private int mRadius;
private int mDistance;
private int mOvalTop;
private int mOvalHeight;
private int mOvalWidth;
/** * 所有形狀的中心位置 */
private int mCenterX, mCenterY;
private int currentCenterY;
private Animator mRotationAnim;
private ValueAnimator mLineAnimDown;
private ValueAnimator mLineAnimUp;
private Shape shape;
public MyLoadingView(Context context)
{
this(context, null);
}
public MyLoadingView(Context context, AttributeSet attrs)
{
super(context);
this.mContext = context;
this.mResource = context.getResources();
init();
}
private void init()
{
mRadius = 10;
mDistance = 50;
mOvalHeight = 3;
mOvalWidth = 10;
mOvalTop = 25;
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Style.FILL);
mPaint.setColor(mResource.getColor(R.color.rect));
mOvalPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mOvalPaint.setStyle(Style.FILL);
mOvalPaint.setColor(mResource.getColor(R.color.color_666666));
setupAnimations();
shape = Shape.RECT;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
/** * 寬度最長是矩形的寬,高度最高是矩形的高加上distance */
int width = (mRadius * 2);
int height = (mDistance + mRadius * 2 + mOvalTop + mOvalHeight);
setMeasuredDimension(width, height);
currentCenterY = mCenterX = mCenterY = mRadius;
}
@Override
protected void onDraw(Canvas canvas)
{
switch (shape)
{
case RECT:
drawRect(canvas);
break;
case TRAIL:
drawTrail(canvas);
break;
case CIRCLE:
drawCircle(canvas);
break;
}
drawOval(canvas);
}
/** * 更具中心點的改變,繪制矩形 */
private void drawRect(Canvas canvas)
{
canvas.drawRect(mCenterX - mRadius, currentCenterY - mRadius, mCenterX + mRadius, currentCenterY + mRadius,
mPaint);
}
private void drawTrail(Canvas canvas)
{
Path path = new Path();
int leftX = 0;
int leftY = currentCenterY + mRadius;
int middleX = mCenterX;
int middleY = currentCenterY - mRadius;
int rightX = mCenterX + mRadius;
int rightY = currentCenterY + mRadius;
path.moveTo(leftX, leftY);
path.lineTo(middleX, middleY);
path.lineTo(rightX, rightY);
path.close();
canvas.drawPath(path, mPaint);
}
private void drawCircle(Canvas canvas)
{
canvas.drawCircle(mCenterX, currentCenterY, mRadius, mPaint);
}
private void drawOval(Canvas canvas)
{
float factory = ((mDistance + mRadius) - currentCenterY) / (float) mDistance;
RectF rectF = new RectF(mCenterX - mOvalWidth * factory, mDistance + mRadius * 2 + mOvalTop, mCenterX
+ mOvalWidth * factory, mDistance + mRadius * 2 + mOvalTop + mOvalHeight);
canvas.drawOval(rectF, mOvalPaint);
}
private void setupAnimations()
{
mRotationAnim = ValueAnimator.ofInt(0, 180);
mLineAnimDown = ValueAnimator.ofInt(mCenterY + mRadius, mDistance);
mLineAnimDown.setInterpolator(new AccelerateInterpolator(1.2f));
mLineAnimDown.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator)
{
currentCenterY = (Integer) valueAnimator.getAnimatedValue();
invalidate();
}
});
mLineAnimUp = ValueAnimator.ofInt(mDistance, mCenterY + mRadius);
mLineAnimUp.setInterpolator(new DecelerateInterpolator(1.2f));
mLineAnimUp.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator)
{
currentCenterY = (Integer) valueAnimator.getAnimatedValue();
invalidate();
}
});
mLineAnimDown.addListener(new AnimatorListenerAdapter()
{
@Override
public void onAnimationEnd(Animator animation)
{
if (shape == Shape.RECT)
{
mPaint.setColor(mResource.getColor(R.color.triangle));
shape = Shape.TRAIL;
}
else
{
if (shape == Shape.TRAIL)
{
mPaint.setColor(mResource.getColor(R.color.circle));
shape = Shape.CIRCLE;
}
else
{
mPaint.setColor(mResource.getColor(R.color.rect));
shape = Shape.RECT;
}
}
}
});
final AnimatorSet set = new AnimatorSet();
set.addListener(new AnimatorListener()
{
@Override
public void onAnimationStart(Animator animation)
{
}
@Override
public void onAnimationRepeat(Animator animation)
{
}
@Override
public void onAnimationEnd(Animator animation)
{
set.start();
}
@Override
public void onAnimationCancel(Animator animation)
{
}
});
set.playSequentially(mLineAnimDown, mLineAnimUp);
set.setDuration(300);
set.setStartDelay(100);
set.start();
}
private enum Shape
{
RECT, TRAIL, CIRCLE;
}
}
用法:直接在布局中引入即可。
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res /android"
xmlns:app="
<view.MyLoadingView
android:id="@+id/loadView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
</RelativeLayout></pre>
之前看到一個開源View整個動畫都是用ViewAnimator銜接起來的,感覺這種方式非常的好,我也嘗試的用這種方式實現。
擴張:自定義 View中我為方便將一些屬性等的都直接指定了,更好的方式是以自定義屬性的方式使用更好。
</div>
本文由用戶 oint1572 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!