Android仿58同城Loading View

oint1572 10年前發布 | 15K 次閱讀 Android開發 移動開發

來自: 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 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!