Dưới đây là mã đầy đủ chức năng mà sẽ động dọc theo một con đường cong được xác định bởi ba điểm. Một điểm chỉ là một lớp giữ một giá trị x và một giá trị y (mặc dù bạn có thể dễ dàng mở rộng nó cho nhiều thứ nguyên hơn).
Tất cả các biến m được lấy từ TranslateAnimation và được sử dụng theo cách tương tự, vì vậy bạn có thể so sánh nó với mã TranslateAnimation tương đối không hài lòng nếu có điều gì đó không hợp lý.
Các cuộc gọi để giải quyếtSize in initialize có nghĩa là bạn có thể chỉ định bắt đầu, kết thúc và bán kính của vòng cung bằng bất kỳ loại hoạt ảnh nào (ABSOLUTE, RELATIVE_TO_SELF, RELATIVE_TO_PARENT) giống như bạn làm cho một TranslateAnimation bình thường.
calcBezier tính đường cong bezier bậc hai được lấy trực tiếp từ Wikipedia. Đường cong Bezier được cho là cho phép mở rộng quy mô trơn tru và phổ biến trong đồ họa (và cũng được sử dụng trong lớp Đường dẫn của Android).
Chuyển động thực tế xảy ra trong applyTransformation. interpolatedTime cho một giá trị từ 0 đến 1, làm tăng phi tuyến tùy thuộc vào nội suy cung cấp. dx và dy là các điểm x và y thực tế dọc theo đường cong trong một thời gian nhất định.
Hạn chế duy nhất của lớp này là thay đổi lớn nhất trong y luôn xảy ra ở trung tâm của đường cong (xem tính toán cho trungX trong khởi tạo). Tuy nhiên, nó sẽ dễ dàng sửa đổi, ví dụ, để cung cấp cho một điểm cụ thể dọc theo đường cong mà tại đó điểm cao sẽ xảy ra nếu bạn muốn có một đường cong không đối xứng.
Nhìn vào mã Android cho TranslateAnimation đặc biệt hữu ích.Xem: 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);
}
}
Xem câu trả lời này: [Chuẩn bị đường cong dịch hoạt hình trong Android] (http://stackoverflow.com/questions/8354441/how-to-prepare-curve-translate-animation-for- android/27948353 # 27948353) – Sheharyar