天天看點

添加購物車效果

做一個商品加入購物車的效果,之前一直想嘗試去實作,無奈啊,沒機會。緻謝 nianxin 徐宜生

001.gif

怎麼用?

<pre>

public void addAction(View view) {

new DriftingTextView(this)

.startView(view)

.rootView(getWindow().getDecorView())

.endView(btCart)

.startBesselAnim();

}

</pre>

代碼很少

package github.alex.jumpview;

import android.animation.Animator;

import android.animation.AnimatorListenerAdapter;

import android.animation.TypeEvaluator;

import android.animation.ValueAnimator;

import android.content.Context;

import android.graphics.Color;

import android.graphics.Point;

import android.graphics.drawable.GradientDrawable;

import android.os.Build;

import android.util.AttributeSet;

import android.util.TypedValue;

import android.view.Gravity;

import android.view.View;

import android.view.ViewGroup;

import android.view.animation.AccelerateDecelerateInterpolator;

import android.widget.TextView;

/**

* 漂移的文本控件

* 作者:alex

* 時間:2016/7/28 10:54

* 部落格位址:

http://www.jianshu.com/users/c3c4ea133871/subscriptions

*/

public class DriftingTextView extends TextView {

private GradientDrawable gradientDrawable;

private static final int VIEW_SIZE = 20;

/\*\*
 \* 控件的半徑
 \*/
protected int radius;
/\*\*
 \* 起點
 \*/
protected Point startPoint;
/\*\*
 \* 終點
 \*/
protected Point endPoint;
/\*\*
 \* 漂移的時間
 \*/
private long driftingDuration;

public DriftingTextView(Context context) {
    super(context);
    initView();
}

public DriftingTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
    initView();
}

private void initView() {
    driftingDuration = 500;
    gradientDrawable = new GradientDrawable();
    gradientDrawable.setShape(GradientDrawable.OVAL);
    gradientDrawable.setColor(Color.parseColor("#FF0000"));
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        setBackground(gradientDrawable);
    } else {
        setBackgroundDrawable(gradientDrawable);
    }
    setGravity(Gravity.CENTER);
    setText("1");
    setTextColor(Color.WHITE);
    setTextSize(10);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int size = (int) dp2Px(VIEW_SIZE);
    setMeasuredDimension(size, size);
    radius = size / 2;
}

/\*\*
 \* 設定  起始點
 \*/
public DriftingTextView startPoint(Point startPoint) {
    startPoint.y -= 10;
    this.startPoint = startPoint;
    return this;
}

/\*\*
 \* 設定 起始點的 控件
 \*/
public DriftingTextView startView(View view) {
    int position[] = new int[2];
    view.getLocationInWindow(position);
    startPoint(new Point(position[0], position[1]));
    return this;
}

/\*\*
 \* 設定 結束點
 \*/
public DriftingTextView endPoint(Point endPoint) {
    this.endPoint = endPoint;
    return this;
}

/\*\*
 \* 設定 結束點的 控件
 \*/
public DriftingTextView endView(View view) {
    int position[] = new int[2];
    view.getLocationInWindow(position);
    endPoint(new Point(position[0], position[1]));
    return this;
}

/\*\*
 \* 設定漂移文本控件的 父控件
 \*/
public DriftingTextView rootView(ViewGroup viewGroup) {
    viewGroup.addView(this);
    return this;
}
/\*\*
 \* 設定漂移文本控件的 父控件
 \*/
public DriftingTextView rootView(View view) {
    if(view instanceof ViewGroup){
        ViewGroup viewGroup = (ViewGroup) view;
        viewGroup.addView(this);
    }
    return this;
}

/\*\*
 \* 設定 漂移時間
 \*
 \* @param driftingDuration 漂移時間,機關 ms
 \*                         如果小于 20ms,或者大于 5000ms,使用預設時間500ms
 \*/
public DriftingTextView driftingDuration(long driftingDuration) {
    if ((driftingDuration < 20) || (driftingDuration > 5000)) {
        driftingDuration = 500;
    }
    this.driftingDuration = driftingDuration;
    return this;
}

public void startBesselAnim() {
    if (startPoint == null || endPoint == null) return;
    int pointX = (startPoint.x + endPoint.x) / 2;
    int pointY = (int) (startPoint.y - dp2Px(100));
    Point driftingPoint = new Point(pointX, pointY);
    BesselEvaluator bezierEvaluator = new BesselEvaluator(driftingPoint);
    ValueAnimator anim = ValueAnimator.ofObject(bezierEvaluator, startPoint, endPoint);
    anim.addUpdateListener(new MyAnimatorUpdateListener());
    anim.setDuration(driftingDuration);
    anim.addListener(new MyAnimatorListenerAdapter());
    anim.setInterpolator(new AccelerateDecelerateInterpolator());
    anim.start();
}

private final class MyAnimatorListenerAdapter extends AnimatorListenerAdapter {
    @Override
    public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
        ViewGroup viewGroup = (ViewGroup) getParent();
        viewGroup.removeView(DriftingTextView.this);
    }
}

private final class MyAnimatorUpdateListener implements ValueAnimator.AnimatorUpdateListener {
    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        Point point = (Point) valueAnimator.getAnimatedValue();
        setX(point.x);
        setY(point.y);
        invalidate();
    }
}

public class BesselEvaluator implements TypeEvaluator<Point> {

    private Point driftingPoint;

    public BesselEvaluator(Point driftingPoint) {
        this.driftingPoint = driftingPoint;
    }

    @Override
    public Point evaluate(float t, Point startValue, Point endValue) {
        int x = (int) ((1 - t) \* (1 - t) \* startValue.x + 2 \* t \* (1 - t) \* driftingPoint.x + t \* t \* endValue.x);
        int y = (int) ((1 - t) \* (1 - t) \* startValue.y + 2 \* t \* (1 - t) \* driftingPoint.y + t \* t \* endValue.y);
        return new Point(x, y);
    }
}

/\*\*
 \* 資料轉換: dp---->px
 \*/
private float dp2Px(float dp) {
    return dp \* getContext().getResources().getDisplayMetrics().density;
}

/\*\*
 \* sp轉px
 \*/
private float sp2px(float sp) {
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getContext().getResources().getDisplayMetrics());
}
           

public class BezierUtil {

/\*\*
 \* B(t) = (1 - t)^2 \* P0 + 2t \* (1 - t) \* P1 + t^2 \* P2, t ∈ [0,1]
 \*
 \* @param t  曲線長度比例
 \* @param p0 起始點
 \* @param p1 控制點
 \* @param p2 終止點
 \* @return t對應的點
 \*/
public static PointF CalculateBezierPointForQuadratic(float t, PointF p0, PointF p1, PointF p2) {
    PointF point = new PointF();
    float temp = 1 - t;
    point.x = temp \* temp \* p0.x + 2 \* t \* temp \* p1.x + t \* t \* p2.x;
    point.y = temp \* temp \* p0.y + 2 \* t \* temp \* p1.y + t \* t \* p2.y;
    return point;
}

/\*\*
 \* B(t) = P0 \* (1-t)^3 + 3 \* P1 \* t \* (1-t)^2 + 3 \* P2 \* t^2 \* (1-t) + P3 \* t^3, t ∈ [0,1]
 \*
 \* @param t  曲線長度比例
 \* @param p0 起始點
 \* @param p1 控制點1
 \* @param p2 控制點2
 \* @param p3 終止點
 \* @return t對應的點
 \*/
public static PointF CalculateBezierPointForCubic(float t, PointF p0, PointF p1, PointF p2, PointF p3) {
    PointF point = new PointF();
    float temp = 1 - t;
    point.x = p0.x \* temp \* temp \* temp + 3 \* p1.x \* t \* temp \* temp + 3 \* p2.x \* t \* t \* temp + p3.x \* t \* t \* t;
    point.y = p0.y \* temp \* temp \* temp + 3 \* p1.y \* t \* temp \* temp + 3 \* p2.y \* t \* t \* temp + p3.y \* t \* t \* t;
    return point;
}