2010-09-27 89 views
25

我得到奇怪的結果用下面的代碼:繪製對象旋轉圍繞其中心的Android

iv = (ImageView) findViewById(R.id.iv); 
     iv.setImageResource(R.drawable.spinner_white_76); 

     Animation a = new RotateAnimation(0.0f, 360.0f, 
       Animation.RELATIVE_TO_SELF, iv.getDrawable() 
         .getIntrinsicWidth()/2, Animation.RELATIVE_TO_SELF, 
       iv.getDrawable().getIntrinsicHeight()/2); 
     a.setRepeatCount(-1); 
     a.setDuration(1000); 

     iv.startAnimation(a); 

請告訴我指定軸點(提拉的中心)的正確方法?

回答

54

感覺蠢!心動不如花一些時間仔細閱讀文檔後,開始工作:

Animation a = new RotateAnimation(0.0f, 360.0f, 
       Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 
       0.5f); 
     a.setRepeatCount(-1); 
     a.setDuration(1000); 
+16

添加 「a.setInterpolator(新LinearInterpolator());」 使旋轉更平滑一些。 – 2012-07-18 15:00:55

+1

我想旋轉180度但不重複。旋轉後,對象將處於最終狀態,我的意思是它不會回到起始位置。我怎樣才能做到這一點? – 2015-02-16 21:49:51

+2

@Md Omar Faroque Anik:添加「a.setFillAfter(true);」使轉換持久化和「a.setRepeatCount(0);」不重複。 – Bubu 2015-03-23 16:09:35

5

需要注意的是,如果你的對象有不對稱的填充(例如爲5px的左填充和0像素的右填充),這是行不通的,因爲填充被視爲對象的一部分。這意味着計算中心將被抵消。

解決此問題的一個辦法是使用邊距而不是填充,如果您使用填充進行佈局原因。正如API在利潤率方面所說:「這個空間超出了這個觀點的界限。」 (ViewGroup.MarginLayoutParams

這意味着邊距不會像填充一樣旋轉。

+0

我該如何告訴'RotateAnimation'考慮邊距? – 2013-04-28 20:13:28

3

這個問題的標題是可繪製圍繞它的中心旋轉(我正在尋找它,沒有找到它並且必須自己實現)想發佈我的解決方案/答案。

我最終寫了自定義drawable,它可以包裝任何drawable並允許它的旋轉。下面是代碼:

public class RotatableDrawable extends DrawableWrapper { 

    private float rotation; 
    private Rect bounds; 
    private ObjectAnimator animator; 
    private long defaultAnimationDuration; 

    public RotatableDrawable(Resources resources, Drawable drawable) { 
     super(vectorToBitmapDrawableIfNeeded(resources, drawable)); 
     bounds = new Rect(); 
     defaultAnimationDuration = resources.getInteger(android.R.integer.config_mediumAnimTime); 
    } 

    @Override 
    public void draw(Canvas canvas) { 
     copyBounds(bounds); 
     canvas.save(); 
     canvas.rotate(rotation, bounds.centerX(), bounds.centerY()); 
     super.draw(canvas); 
     canvas.restore(); 
    } 

    public void rotate(float degrees) { 
     rotate(degrees, defaultAnimationDuration); 
    } 

    public void rotate(float degrees, long millis) { 
     if (null != animator && animator.isStarted()) { 
      animator.end(); 
     } else if (null == animator) { 
      animator = ObjectAnimator.ofFloat(this, "rotation", 0, 0); 
      animator.setInterpolator(new AccelerateDecelerateInterpolator()); 
     } 
     animator.setFloatValues(rotation, degrees); 
     animator.setDuration(millis).start(); 
    } 

    @AnimatorSetter 
    public void setRotation(float degrees) { 
     this.rotation = degrees % 360; 
     invalidateSelf(); 
    } 

    /** 
    * Workaround for issues related to vector drawables rotation and scaling: 
    * https://code.google.com/p/android/issues/detail?id=192413 
    * https://code.google.com/p/android/issues/detail?id=208453 
    */ 
    private static Drawable vectorToBitmapDrawableIfNeeded(Resources resources, Drawable drawable) { 
     if (drawable instanceof VectorDrawable) { 
      Bitmap b = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); 
      Canvas c = new Canvas(b); 
      drawable.setBounds(0, 0, c.getWidth(), c.getHeight()); 
      drawable.draw(c); 
      drawable = new BitmapDrawable(resources, b); 
     } 
     return drawable; 
    } 
} 
+0

@AnimatorSetter是什麼? – 2016-11-26 17:18:37

+0

糟糕...這只是我的自定義註釋。我用它來向ProGuard和Android工作室表明這種方法實際上用於動畫。 (ObjectAnimator.ofFloat(this,「rotation」,0,0);在執行過程中調用setRotation) – GregoryK 2016-11-27 06:58:39

+0

這個類需要保存在ProGuard中,而VectorDrawable會導致前Lollipop崩潰,除非你使用vector drawables 。 – 2016-11-28 00:19:13