2011-07-27 43 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