FileDocCategorySizeDatePackage
PathKeyframes.javaAPI DocAndroid 5.1 API8285Thu Mar 12 22:22:08 GMT 2015android.animation

PathKeyframes

public class PathKeyframes extends Object implements Keyframes
PathKeyframes relies on approximating the Path as a series of line segments. The line segments are recursively divided until there is less than 1/2 pixel error between the lines and the curve. Each point of the line segment is converted to a Keyframe and a linear interpolation between Keyframes creates a good approximation of the curve.

PathKeyframes is optimized to reduce the number of objects created when there are many keyframes for a curve.

Typically, the returned type is a PointF, but the individual components can be extracted as either an IntKeyframes or FloatKeyframes.

Fields Summary
private static final int
FRACTION_OFFSET
private static final int
X_OFFSET
private static final int
Y_OFFSET
private static final int
NUM_COMPONENTS
private static final ArrayList
EMPTY_KEYFRAMES
private android.graphics.PointF
mTempPointF
private float[]
mKeyframeData
Constructors Summary
public PathKeyframes(android.graphics.Path path)


       
        this(path, 0.5f);
    
public PathKeyframes(android.graphics.Path path, float error)

        if (path == null || path.isEmpty()) {
            throw new IllegalArgumentException("The path must not be null or empty");
        }
        mKeyframeData = path.approximate(error);
    
Methods Summary
public Keyframesclone()

        Keyframes clone = null;
        try {
            clone = (Keyframes) super.clone();
        } catch (CloneNotSupportedException e) {}
        return clone;
    
public FloatKeyframescreateXFloatKeyframes()
Returns a FloatKeyframes for the X component of the Path.

return
a FloatKeyframes for the X component of the Path.

        return new FloatKeyframesBase() {
            @Override
            public float getFloatValue(float fraction) {
                PointF pointF = (PointF) PathKeyframes.this.getValue(fraction);
                return pointF.x;
            }
        };
    
public IntKeyframescreateXIntKeyframes()
Returns an IntKeyframes for the X component of the Path.

return
an IntKeyframes for the X component of the Path.

        return new IntKeyframesBase() {
            @Override
            public int getIntValue(float fraction) {
                PointF pointF = (PointF) PathKeyframes.this.getValue(fraction);
                return Math.round(pointF.x);
            }
        };
    
public FloatKeyframescreateYFloatKeyframes()
Returns a FloatKeyframes for the Y component of the Path.

return
a FloatKeyframes for the Y component of the Path.

        return new FloatKeyframesBase() {
            @Override
            public float getFloatValue(float fraction) {
                PointF pointF = (PointF) PathKeyframes.this.getValue(fraction);
                return pointF.y;
            }
        };
    
public IntKeyframescreateYIntKeyframes()
Returns an IntKeyframeSet for the Y component of the Path.

return
an IntKeyframeSet for the Y component of the Path.

        return new IntKeyframesBase() {
            @Override
            public int getIntValue(float fraction) {
                PointF pointF = (PointF) PathKeyframes.this.getValue(fraction);
                return Math.round(pointF.y);
            }
        };
    
public java.util.ArrayListgetKeyframes()

        return EMPTY_KEYFRAMES;
    
public java.lang.ClassgetType()

        return PointF.class;
    
public java.lang.ObjectgetValue(float fraction)

        int numPoints = mKeyframeData.length / 3;
        if (fraction < 0) {
            return interpolateInRange(fraction, 0, 1);
        } else if (fraction > 1) {
            return interpolateInRange(fraction, numPoints - 2, numPoints - 1);
        } else if (fraction == 0) {
            return pointForIndex(0);
        } else if (fraction == 1) {
            return pointForIndex(numPoints - 1);
        } else {
            // Binary search for the correct section
            int low = 0;
            int high = numPoints - 1;

            while (low <= high) {
                int mid = (low + high) / 2;
                float midFraction = mKeyframeData[(mid * NUM_COMPONENTS) + FRACTION_OFFSET];

                if (fraction < midFraction) {
                    high = mid - 1;
                } else if (fraction > midFraction) {
                    low = mid + 1;
                } else {
                    return pointForIndex(mid);
                }
            }

            // now high is below the fraction and low is above the fraction
            return interpolateInRange(fraction, high, low);
        }
    
private static floatinterpolate(float fraction, float startValue, float endValue)

        float diff = endValue - startValue;
        return startValue + (diff * fraction);
    
private android.graphics.PointFinterpolateInRange(float fraction, int startIndex, int endIndex)

        int startBase = (startIndex * NUM_COMPONENTS);
        int endBase = (endIndex * NUM_COMPONENTS);

        float startFraction = mKeyframeData[startBase + FRACTION_OFFSET];
        float endFraction = mKeyframeData[endBase + FRACTION_OFFSET];

        float intervalFraction = (fraction - startFraction)/(endFraction - startFraction);

        float startX = mKeyframeData[startBase + X_OFFSET];
        float endX = mKeyframeData[endBase + X_OFFSET];
        float startY = mKeyframeData[startBase + Y_OFFSET];
        float endY = mKeyframeData[endBase + Y_OFFSET];

        float x = interpolate(intervalFraction, startX, endX);
        float y = interpolate(intervalFraction, startY, endY);

        mTempPointF.set(x, y);
        return mTempPointF;
    
public voidinvalidateCache()

    
private android.graphics.PointFpointForIndex(int index)

        int base = (index * NUM_COMPONENTS);
        int xOffset = base + X_OFFSET;
        int yOffset = base + Y_OFFSET;
        mTempPointF.set(mKeyframeData[xOffset], mKeyframeData[yOffset]);
        return mTempPointF;
    
public voidsetEvaluator(TypeEvaluator evaluator)