2011-07-27 69 views
5

可能重複:
Android, move bitmap along a path?問題,實現彎曲動畫

我想通過彎曲path.Is可以在Android的移動圖像?我搜索了很多,但我只能找到有關規模,旋轉和翻譯動畫。所以任何人有任何想法請help.Is它可能在Android?

+0

看到這個答案:[準備曲線的Android翻譯動畫(http://stackoverflow.com/questions/8354441/how-to-prepare-curve-translate-animation-for- android/27948353#27948353) – Sheharyar

回答

1

您可以執行逐幀動畫。您可以逐步放置對象以創建曲線。這將是有限的重用,但你可以做到。

或者您可以編寫自己的動畫來創建TweenAnimation的子類,該子類可以沿着曲線進行動畫製作。如果你擅長數學並且能夠理解貝塞爾曲線,那麼這可能是一個直截了當的選擇。一旦你有了這門課程,你就可以輕鬆地在任何彎曲的路徑上進行動畫製作,但這更加有效。

http://en.wikipedia.org/wiki/B%C3%A9zier_curve

這裏的一些Java代碼:

http://www.math.ubc.ca/~cass/gfx/bezier.html

+0

Thanks.Do你有任何示例或任何職位的任何鏈接? –

+0

你能告訴我如何創建我自己的動畫類作爲tweenanimation的子類。 –

9

下面是全功能的代碼,將沿三個點定義的曲線路徑動畫。 Point只是一個擁有x值和y值的類(儘管您可以輕鬆地將其擴展爲更多維)。

所有的m變量都取自TranslateAnimation並以類似的方式使用,所以如果某些東西沒有意義,您應該可以將它與TranslateAnimation代碼相對比較eaSILY。

在initialize中對resolveSize的調用意味着您可以使用任何動畫類型(ABSOLUTE,RELATIVE_TO_SELF,RELATIVE_TO_PARENT)指定弧的開始,結束和半徑,就像正常的TranslateAnimation一樣。

calcBezier計算直接從Wikipedia取得的二次貝塞爾曲線。 Bezier曲線應該允許平滑縮放,並且在圖形中很常見(並且在Android的Path類中也有使用)。

實際運動發生在applyTransformation中。 interpolatedTime給出一個介於0和1之間的值,該值根據所提供的內插器非線性增加。 dx和dy是給定時間沿曲線的實際x和y點。

這個類的唯一限制是在y中的最大變化總是發生在曲線的中心(參見初始化middleX計算)。但是它會很容易修改,例如,提供沿處,如果你想有一個非對稱的曲線應該發生在高點的曲線上的特定點。

查看TranslateAnimation的android代碼特別有用。請參閱:http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.5_r1/android/view/animation/TranslateAnimation.java#TranslateAnimation

public class ArcTranslate extends Animation { 

private Point start; 
private Point end; 
private Point middle; 
private final float mFromXValue; 
private final float mToXValue; 
private final float mYValue; 
private final int mFromXType; 
private final int mToXType; 
private final int mYType; 

/** 
* A translation along an arc defined by three points and a Bezier Curve 
* 
* @param duration - the time in ms it will take for the translation to complete 
* @param fromXType - One of Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or Animation.RELATIVE_TO_PARENT. 
* @param fromXValue - Change in X coordinate to apply at the start of the animation 
* @param toXType - One of Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or Animation.RELATIVE_TO_PARENT. 
* @param toXValue - Change in X coordinate to apply at the end of the animation 
* @param yType - One of Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or Animation.RELATIVE_TO_PARENT. 
* @param yValue - Change in Y coordinate to apply at the middle of the animation (the radius of the arc) 
*/ 
public ArcTranslate(long duration, int fromXType, float fromXValue, 
     int toXType, float toXValue, int yType, float yValue){ 
    setDuration(duration); 

    mFromXValue = fromXValue; 
    mToXValue = toXValue; 
    mYValue = yValue; 

    mFromXType = fromXType; 
    mToXType = toXType; 
    mYType = yType; 

} 

/** Calculate the position on a quadratic bezier curve given three points 
* and the percentage of time passed. 
* from http://en.wikipedia.org/wiki/B%C3%A9zier_curve 
* @param interpolatedTime - the fraction of the duration that has passed where 0<=time<=1 
* @param p0 - a single dimension of the starting point 
* @param p1 - a single dimension of the middle point 
* @param p2 - a single dimension of the ending point 
*/ 
private long calcBezier(float interpolatedTime, float p0, float p1, float p2){ 
    return Math.round((Math.pow((1 - interpolatedTime), 2) * p0) 
      + (2 * (1 - interpolatedTime) * interpolatedTime * p1) 
      + (Math.pow(interpolatedTime, 2) * p2)); 
} 

@Override 
protected void applyTransformation(float interpolatedTime, Transformation t) { 
    float dx = calcBezier(interpolatedTime, start.x, middle.x, end.x); 
    float dy = calcBezier(interpolatedTime, start.y, middle.y, end.y); 

    t.getMatrix().setTranslate(dx, dy); 
} 

@Override 
public void initialize(int width, int height, int parentWidth, int parentHeight) { 
    super.initialize(width, height, parentWidth, parentHeight); 
    float startX = resolveSize(mFromXType, mFromXValue, width, parentWidth); 
    float endX = resolveSize(mToXType, mToXValue, width, parentWidth); 
    float middleY = resolveSize(mYType, mYValue, width, parentWidth); 
    float middleX = startX + ((endX-startX)/2); 
    start = new Point(startX, 0); 
    end = new Point(endX, 0); 
    middle = new Point(middleX, middleY); 
} 
} 
+0

@Monkeyless非常感謝你的代碼。我設法使用此代碼爲imageview設置動畫效果。但是在動畫時,我無法將onClickListener設置爲圖像視圖。我發佈了一個問題[這裏](http://stackoverflow.com/questions/23947114/onclicklistener-not-triggered-during-animation)。請幫忙。 –

0

您可以創建自己的類這樣的:

public class BezierTranslateAnimation extends TranslateAnimation { 

private int mFromXType = ABSOLUTE; 
private int mToXType  = ABSOLUTE; 
private int mFromYType = ABSOLUTE; 
private int mToYType  = ABSOLUTE; 
private float mFromXValue = 0.0f; 
private float mToXValue = 0.0f; 
private float mFromYValue = 0.0f; 
private float mToYValue = 0.0f; 
private float mFromXDelta; 
private float mToXDelta; 
private float mFromYDelta; 
private float mToYDelta; 
private float mBezierXDelta; 
private float mBezierYDelta; 

public BezierTranslateAnimation(float fromXDelta, float toXDelta,float fromYDelta, float toYDelta, float bezierXDelta, float bezierYDelta) { 
    super(fromXDelta, toXDelta, fromYDelta, toYDelta); 

     mFromXValue = fromXDelta; 
     mToXValue = toXDelta; 
     mFromYValue = fromYDelta; 
     mToYValue = toYDelta; 
     mFromXType = ABSOLUTE; 
     mToXType = ABSOLUTE; 
     mFromYType = ABSOLUTE; 
     mToYType = ABSOLUTE; 
     mBezierXDelta = bezierXDelta; 
     mBezierYDelta = bezierYDelta; 

} 



@Override 
protected void applyTransformation(float interpolatedTime, Transformation t) { 

    float dx=0,dy=0; 

    if (mFromXValue != mToXValue) { 

     dx = (float) ((1.0-interpolatedTime)*(1.0-interpolatedTime)*mFromXValue + 2.0*interpolatedTime*(1.0-interpolatedTime)*mBezierXDelta + interpolatedTime*interpolatedTime*mToXValue); 
    } 

    if (mFromYValue != mToYValue) { 

     dy = (float) ((1.0-interpolatedTime)*(1.0-interpolatedTime)*mFromYValue + 2.0*interpolatedTime*(1.0-interpolatedTime)*mBezierYDelta + interpolatedTime*interpolatedTime*mToYValue); 
    } 

    t.getMatrix().setTranslate(dx, dy); 

    } 

} 

然後用這個簽名使用它:

BezierTranslateAnimation(float fromXDelta, float toXDelta,float fromYDelta, float toYDelta, float bezierXDelta, float bezierYDelta); 
+0

你不使用動畫的類型... –

5

它是由Monkeyless的回答啓發。 我創建了動畫的一個子類,使用PathMeasure來計算翻譯。 您可以使用Path創建一個新的PathAnimation,並像其他任何動畫一樣使用它。

https://github.com/coocood/PathAnimation

public class PathAnimation extends Animation { 
private PathMeasure measure; 
private float[] pos = new float[2]; 
public PathAnimation(Path path) { 
    measure = new PathMeasure(path, false); 
} 

@Override 
protected void applyTransformation(float interpolatedTime, Transformation t){ 
    measure.getPosTan(measure.getLength() * interpolatedTime, pos,null); 
    t.getMatrix().setTranslate(pos[0], pos[1]); 
} 
} 
+0

我已經使用Path.addArc()來創建弧我希望我的視圖旅行,然後這個解決方案作爲動畫本身。太好了! – Vaiden

+0

@vaiden,你可以在這裏發表例子嗎? – Geetha

+1

只需創建一個Path對象並將其提供給構造函數。沒有一個真正的例子。 – Vaiden