2014-03-25 236 views
1

你好社區我在想你是否可以幫我解決以下問題。我正在開發一個項目,我需要能夠在觸摸時將位圖移動一定距離。 (快照中的第2步)但是,在到達邊界時,應該將圖像包裝到另一側,如步驟3所示。Android查看屬性動畫

我閱讀屬性動畫製作工具,以及它如何允許發佈視圖,但是我沒有理解是我應該使用什麼樣的佈局。我應該使用RelativeLayout還是LinearLayout?或者我應該使用canvas? 如何屏蔽父視圖(快照中的視圖B)以實現視圖環繞效果。

謝謝你,

enter image description here

回答

0
import android.animation.AnimatorSet; 
import android.animation.ObjectAnimator; 
import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.Matrix; 
import android.graphics.RectF; 
import android.util.AttributeSet; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.animation.AccelerateInterpolator; 
import android.view.animation.DecelerateInterpolator; 
import android.view.animation.LinearInterpolator; 
import android.view.animation.OvershootInterpolator; 
import android.widget.Button; 


public class AnticiButton extends Button { 

    private static final LinearInterpolator sLinearInterpolator = new LinearInterpolator(); 
    private static final DecelerateInterpolator sDecelerator = new DecelerateInterpolator(8); 
    private static final AccelerateInterpolator sAccelerator = new AccelerateInterpolator(); 
    private static final OvershootInterpolator sOvershooter = new OvershootInterpolator(); 
    private static final DecelerateInterpolator sQuickDecelerator = new DecelerateInterpolator(); 

    private float mSkewX = 0; 
    ObjectAnimator downAnim = null; 
    boolean mOnLeft = true; 
    RectF mTempRect = new RectF(); 

    public AnticiButton(Context context) { 
     super(context); 
     init(); 
    } 

    public AnticiButton(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     init(); 
    } 

    public AnticiButton(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     init(); 
    } 

    private void init() { 
     setOnTouchListener(mTouchListener); 
     setOnClickListener(new OnClickListener() { 
      public void onClick(View v) { 
       runClickAnim(); 
      } 
     }); 
    } 


    @Override 
    public void draw(Canvas canvas) { 
     if (mSkewX != 0) { 
      canvas.translate(0, getHeight()); 
      canvas.skew(mSkewX, 0); 
      canvas.translate(0, -getHeight()); 
     } 
     super.draw(canvas); 
    } 


    private void runPressAnim() { 
     downAnim = ObjectAnimator.ofFloat(this, "skewX", mOnLeft ? .5f : -.5f); 
     downAnim.setDuration(2500); 
     downAnim.setInterpolator(sDecelerator); 
     downAnim.start(); 
    } 

    private void runClickAnim() { 
     // Anticipation 
     ObjectAnimator finishDownAnim = null; 
     if (downAnim != null && downAnim.isRunning()) { 
      // finish the skew animation quickly 
      downAnim.cancel(); 
      finishDownAnim = ObjectAnimator.ofFloat(this, "skewX", 
        mOnLeft ? .5f : -.5f); 
      finishDownAnim.setDuration(150); 
      finishDownAnim.setInterpolator(sQuickDecelerator); 
     } 


     ObjectAnimator moveAnim = ObjectAnimator.ofFloat(this, 
       View.TRANSLATION_X, mOnLeft ? 400 : 0); 
     moveAnim.setInterpolator(sLinearInterpolator); 
     moveAnim.setDuration(150); 


     ObjectAnimator skewAnim = ObjectAnimator.ofFloat(this, "skewX", 
       mOnLeft ? -.5f : .5f); 
     skewAnim.setInterpolator(sQuickDecelerator); 
     skewAnim.setDuration(100); 
     // and wobble it 
     ObjectAnimator wobbleAnim = ObjectAnimator.ofFloat(this, "skewX", 0); 
     wobbleAnim.setInterpolator(sOvershooter); 
     wobbleAnim.setDuration(150); 
     AnimatorSet set = new AnimatorSet(); 
     set.playSequentially(moveAnim, skewAnim, wobbleAnim); 
     if (finishDownAnim != null) { 
      set.play(finishDownAnim).before(moveAnim); 
     } 
     set.start(); 
     mOnLeft = !mOnLeft; 
    } 


    private void runCancelAnim() { 
     if (downAnim != null && downAnim.isRunning()) { 
      downAnim.cancel(); 
      ObjectAnimator reverser = ObjectAnimator.ofFloat(this, "skewX", 0); 
      reverser.setDuration(200); 
      reverser.setInterpolator(sAccelerator); 
      reverser.start(); 
      downAnim = null; 
     } 
    } 


    private View.OnTouchListener mTouchListener = new View.OnTouchListener() { 

     @Override 
     public boolean onTouch(View v, MotionEvent event) { 
      switch (event.getAction()) { 
      case MotionEvent.ACTION_UP: 
       if (isPressed()) { 
        performClick(); 
        setPressed(false); 
        break; 
       } 
       // No click: Fall through; equivalent to cancel event 
      case MotionEvent.ACTION_CANCEL: 
       // Run the cancel animation in either case 
       runCancelAnim(); 
       break; 
      case MotionEvent.ACTION_MOVE: 
       float x = event.getX(); 
       float y = event.getY(); 
       boolean isInside = (x > 0 && x < getWidth() && 
         y > 0 && y < getHeight()); 
       if (isPressed() != isInside) { 
        setPressed(isInside); 
       } 
       break; 
      case MotionEvent.ACTION_DOWN: 
       setPressed(true); 
       runPressAnim(); 
       break; 
      default: 
       break; 
      } 
      return true; 
     } 
    }; 

    public float getSkewX() { 
     return mSkewX; 
    } 


    public void setSkewX(float value) { 
     if (value != mSkewX) { 
      mSkewX = value; 
      invalidate();    // force button to redraw with new skew value 
      invalidateSkewedBounds(); // also invalidate appropriate area of parent 
     } 
    } 


    private void invalidateSkewedBounds() { 
     if (mSkewX != 0) { 
      Matrix matrix = new Matrix(); 
      matrix.setSkew(-mSkewX, 0); 
      mTempRect.set(0, 0, getRight(), getBottom()); 
      matrix.mapRect(mTempRect); 
      mTempRect.offset(getLeft() + getTranslationX(), getTop() + getTranslationY()); 
      ((View) getParent()).invalidate((int) mTempRect.left, (int) mTempRect.top, 
        (int) (mTempRect.right +.5f), (int) (mTempRect.bottom + .5f)); 
     } 
    } 
} 

加入你的XML佈局:

<view 
     class="com.example.android.anticipation.AnticiButton" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="AnticiButton"/> 

我希望這將有助於