动画按钮时,ViewCompat.postInvalidateOnAnimation(视图v)不起作用

时间:2014-06-18 05:34:54

标签: java android android-animation

我正在尝试制作一个动画按钮,并尝试了一个库代码并在我的项目中实现了可用的代码,除了这个之外,其他每个动画按钮代码都正常工作。

这是代码,如果有人可以帮助我,我会非常感激。

package com.dd.processbutton.iml;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;

import com.dd.processbutton.ProcessButton;
import com.dd.sample.R;

public class ActionProcessButton extends ProcessButton {

    private ProgressBar mProgressBar;

    private Mode mMode;

    private int mColor1;
    private int mColor2;
    private int mColor3;
    private int mColor4;

    public enum Mode {
        PROGRESS, ENDLESS;
    }

    public ActionProcessButton(Context context) {
        super(context);
        init(context);
    }

    public ActionProcessButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public ActionProcessButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    private void init(Context context) {
        Resources res = context.getResources();

        mMode = Mode.ENDLESS;

        mColor1 = res.getColor(R.color.holo_blue_bright);
        mColor2 = res.getColor(R.color.holo_green_light);
        mColor3 = res.getColor(R.color.holo_orange_light);
        mColor4 = res.getColor(R.color.holo_red_light);
    }

    public void setMode(Mode mode) {
        mMode = mode;
    }

    public void setColorScheme(int color1, int color2, int color3, int color4) {
        mColor1 = color1;
        mColor2 = color2;
        mColor3 = color3;
        mColor4 = color4;
    }

    @Override
    public void drawProgress(Canvas canvas) {
        if (getBackground() != getNormalDrawable()) {
            setBackgroundDrawable(getNormalDrawable());
        }

        switch (mMode) {
        case ENDLESS:
            drawEndlessProgress(canvas);
            break;
        case PROGRESS:
            drawLineProgress(canvas);
            break;
        }
    }

    private void drawLineProgress(Canvas canvas) {
        float scale = (float) getProgress() / (float) getMaxProgress();
        float indicatorWidth = (float) getMeasuredWidth() * scale;

        double indicatorHeightPercent = 0.05; // 5%
        int bottom = (int) (getMeasuredHeight() - getMeasuredHeight()
                * indicatorHeightPercent);
        getProgressDrawable().setBounds(0, bottom, (int) indicatorWidth,
                getMeasuredHeight());
        getProgressDrawable().draw(canvas);
    }

    private void drawEndlessProgress(Canvas canvas) {
        double indicatorHeight = getDimension(R.dimen.layer_padding);
        int bottom = (int) (getMeasuredHeight() - indicatorHeight);

        if (mProgressBar == null) {
            mProgressBar = new ProgressBar(this);
            mProgressBar.setBounds(0, bottom, getMeasuredWidth(),
                    getMeasuredHeight());
            mProgressBar.setColorScheme(mColor1, mColor2, mColor3, mColor4);
            mProgressBar.start();
        }

        if (getProgress() > 0) {
            mProgressBar.draw(canvas);
        }
    }

    public static class ProgressBar {

        // Default progress animation colors are grays.
        private final static int COLOR1 = 0xB3000000;
        private final static int COLOR2 = 0x80000000;
        private final static int COLOR3 = 0x4d000000;
        private final static int COLOR4 = 0x1a000000;

        // The duration of the animation cycle.
        private static final int ANIMATION_DURATION_MS = 2000;

        // The duration of the animation to clear the bar.
        private static final int FINISH_ANIMATION_DURATION_MS = 1000;

        // Interpolator for varying the speed of the animation.
        private static final Interpolator INTERPOLATOR = new AccelerateDecelerateInterpolator();

        private final Paint mPaint = new Paint();
        private final RectF mClipRect = new RectF();
        private float mTriggerPercentage;
        private long mStartTime;
        private long mFinishTime;
        private boolean mRunning;

        // Colors used when rendering the animation,
        private int mColor1;
        private int mColor2;
        private int mColor3;
        private int mColor4;
        private View mParent;

        private Rect mBounds = new Rect();

        public ProgressBar(View parent) {
            mParent = parent;
            mColor1 = COLOR1;
            mColor2 = COLOR2;
            mColor3 = COLOR3;
            mColor4 = COLOR4;
        }

        /**
         * Set the four colors used in the progress animation. The first color
         * will also be the color of the bar that grows in response to a user
         * swipe gesture.
         * 
         * @param color1
         *            Integer representation of a color.
         * @param color2
         *            Integer representation of a color.
         * @param color3
         *            Integer representation of a color.
         * @param color4
         *            Integer representation of a color.
         */
        void setColorScheme(int color1, int color2, int color3, int color4) {
            mColor1 = color1;
            mColor2 = color2;
            mColor3 = color3;
            mColor4 = color4;
        }

        /**
         * Start showing the progress animation.
         */
        void start() {
            if (!mRunning) {
                mTriggerPercentage = 0;
                mStartTime = AnimationUtils.currentAnimationTimeMillis();
                mRunning = true;
                mParent.postInvalidate();
            }
        }

        void draw(Canvas canvas) {
            final int width = mBounds.width();
            final int height = mBounds.height();
            final int cx = width / 2;
            final int cy = height / 2;
            boolean drawTriggerWhileFinishing = false;
            int restoreCount = canvas.save();
            canvas.clipRect(mBounds);

            if (mRunning || (mFinishTime > 0)) {
                long now = AnimationUtils.currentAnimationTimeMillis();
                long elapsed = (now - mStartTime) % ANIMATION_DURATION_MS;
                long iterations = (now - mStartTime) / ANIMATION_DURATION_MS;
                float rawProgress = (elapsed / (ANIMATION_DURATION_MS / 100f));

                // If we're not running anymore, that means we're running
                // through
                // the finish animation.
                if (!mRunning) {
                    // If the finish animation is done, don't draw anything, and
                    // don't repost.
                    if ((now - mFinishTime) >= FINISH_ANIMATION_DURATION_MS) {
                        mFinishTime = 0;
                        return;
                    }

                    // Otherwise, use a 0 opacity alpha layer to clear the
                    // animation
                    // from the inside out. This layer will prevent the circles
                    // from
                    // drawing within its bounds.
                    long finishElapsed = (now - mFinishTime)
                            % FINISH_ANIMATION_DURATION_MS;
                    float finishProgress = (finishElapsed / (FINISH_ANIMATION_DURATION_MS / 100f));
                    float pct = (finishProgress / 100f);
                    // Radius of the circle is half of the screen.
                    float clearRadius = width / 2
                            * INTERPOLATOR.getInterpolation(pct);
                    mClipRect
                            .set(cx - clearRadius, 0, cx + clearRadius, height);
                    canvas.saveLayerAlpha(mClipRect, 0, 0);
                    // Only draw the trigger if there is a space in the center
                    // of
                    // this refreshing view that needs to be filled in by the
                    // trigger. If the progress view is just still animating,
                    // let it
                    // continue animating.
                    drawTriggerWhileFinishing = true;
                }

                // First fill in with the last color that would have finished
                // drawing.
                if (iterations == 0) {
                    canvas.drawColor(mColor1);
                } else {
                    if (rawProgress >= 0 && rawProgress < 25) {
                        canvas.drawColor(mColor4);
                    } else if (rawProgress >= 25 && rawProgress < 50) {
                        canvas.drawColor(mColor1);
                    } else if (rawProgress >= 50 && rawProgress < 75) {
                        canvas.drawColor(mColor2);
                    } else {
                        canvas.drawColor(mColor3);
                    }
                }

                // Then draw up to 4 overlapping concentric circles of varying
                // radii, based on how far
                // along we are in the cycle.
                // progress 0-50 draw mColor2
                // progress 25-75 draw mColor3
                // progress 50-100 draw mColor4
                // progress 75 (wrap to 25) draw mColor1
                if ((rawProgress >= 0 && rawProgress <= 25)) {
                    float pct = (((rawProgress + 25) * 2) / 100f);
                    drawCircle(canvas, cx, cy, mColor1, pct);
                }
                if (rawProgress >= 0 && rawProgress <= 50) {
                    float pct = ((rawProgress * 2) / 100f);
                    drawCircle(canvas, cx, cy, mColor2, pct);
                }
                if (rawProgress >= 25 && rawProgress <= 75) {
                    float pct = (((rawProgress - 25) * 2) / 100f);
                    drawCircle(canvas, cx, cy, mColor3, pct);
                }
                if (rawProgress >= 50 && rawProgress <= 100) {
                    float pct = (((rawProgress - 50) * 2) / 100f);
                    drawCircle(canvas, cx, cy, mColor4, pct);
                }
                if ((rawProgress >= 75 && rawProgress <= 100)) {
                    float pct = (((rawProgress - 75) * 2) / 100f);
                    drawCircle(canvas, cx, cy, mColor1, pct);
                }
                if (mTriggerPercentage > 0 && drawTriggerWhileFinishing) {
                    // There is some portion of trigger to draw. Restore the
                    // canvas,
                    // then draw the trigger. Otherwise, the trigger does not
                    // appear
                    // until after the bar has finished animating and appears to
                    // just jump in at a larger width than expected.
                    canvas.restoreToCount(restoreCount);
                    restoreCount = canvas.save();
                    canvas.clipRect(mBounds);
                    drawTrigger(canvas, cx, cy);
                }
                // Keep running until we finish out the last cycle.

                ViewCompat.postInvalidateOnAnimation(mParent);
            } else {
                // Otherwise if we're in the middle of a trigger, draw that.
                if (mTriggerPercentage > 0 && mTriggerPercentage <= 1.0) {
                    drawTrigger(canvas, cx, cy);
                }
            }
            canvas.restoreToCount(restoreCount);
        }

        private void drawTrigger(Canvas canvas, int cx, int cy) {
            mPaint.setColor(mColor1);
            canvas.drawCircle(cx, cy, cx * mTriggerPercentage, mPaint);
        }

        /**
         * Draws a circle centered in the view.
         * 
         * @param canvas
         *            the canvas to draw on
         * @param cx
         *            the center x coordinate
         * @param cy
         *            the center y coordinate
         * @param color
         *            the color to draw
         * @param pct
         *            the percentage of the view that the circle should cover
         */
        private void drawCircle(Canvas canvas, float cx, float cy, int color,
                float pct) {
            mPaint.setColor(color);
            canvas.save();
            canvas.translate(cx, cy);
            float radiusScale = INTERPOLATOR.getInterpolation(pct);
            canvas.scale(radiusScale, radiusScale);
            canvas.drawCircle(0, 0, cx, mPaint);
            canvas.restore();
        }

        /**
         * Set the drawing bounds of this SwipeProgressBar.
         */
        void setBounds(int left, int top, int right, int bottom) {
            mBounds.left = left;
            mBounds.top = top;
            mBounds.right = right;
            mBounds.bottom = bottom;
        }
    }

}

这是我的堆栈跟踪,我不知道发生此错误的原因。

06-18 10:50:59.231: E/AndroidRuntime(322): FATAL EXCEPTION: main
06-18 10:50:59.231: E/AndroidRuntime(322): java.lang.NoClassDefFoundError: android.support.v4.view.ViewCompat
06-18 10:50:59.231: E/AndroidRuntime(322):  at com.dd.processbutton.iml.ActionProcessButton$ProgressBar.draw(ActionProcessButton.java:321)
06-18 10:50:59.231: E/AndroidRuntime(322):  at com.dd.processbutton.iml.ActionProcessButton.drawEndlessProgress(ActionProcessButton.java:136)
06-18 10:50:59.231: E/AndroidRuntime(322):  at com.dd.processbutton.iml.ActionProcessButton.drawProgress(ActionProcessButton.java:103)
06-18 10:50:59.231: E/AndroidRuntime(322):  at com.dd.processbutton.ProcessButton.onDraw(ProcessButton.java:137)
06-18 10:50:59.231: E/AndroidRuntime(322):  at android.view.View.draw(View.java:6880)
06-18 10:50:59.231: E/AndroidRuntime(322):  at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
06-18 10:50:59.231: E/AndroidRuntime(322):  at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
06-18 10:50:59.231: E/AndroidRuntime(322):  at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
06-18 10:50:59.231: E/AndroidRuntime(322):  at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
06-18 10:50:59.231: E/AndroidRuntime(322):  at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
06-18 10:50:59.231: E/AndroidRuntime(322):  at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
06-18 10:50:59.231: E/AndroidRuntime(322):  at android.view.View.draw(View.java:6883)
06-18 10:50:59.231: E/AndroidRuntime(322):  at android.widget.FrameLayout.draw(FrameLayout.java:357)
06-18 10:50:59.231: E/AndroidRuntime(322):  at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
06-18 10:50:59.231: E/AndroidRuntime(322):  at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
06-18 10:50:59.231: E/AndroidRuntime(322):  at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
06-18 10:50:59.231: E/AndroidRuntime(322):  at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
06-18 10:50:59.231: E/AndroidRuntime(322):  at android.view.View.draw(View.java:6883)
06-18 10:50:59.231: E/AndroidRuntime(322):  at android.widget.FrameLayout.draw(FrameLayout.java:357)
06-18 10:50:59.231: E/AndroidRuntime(322):  at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1862)
06-18 10:50:59.231: E/AndroidRuntime(322):  at android.view.ViewRoot.draw(ViewRoot.java:1522)
06-18 10:50:59.231: E/AndroidRuntime(322):  at android.view.ViewRoot.performTraversals(ViewRoot.java:1258)
06-18 10:50:59.231: E/AndroidRuntime(322):  at android.view.ViewRoot.handleMessage(ViewRoot.java:1859)
06-18 10:50:59.231: E/AndroidRuntime(322):  at android.os.Handler.dispatchMessage(Handler.java:99)
06-18 10:50:59.231: E/AndroidRuntime(322):  at android.os.Looper.loop(Looper.java:123)
06-18 10:50:59.231: E/AndroidRuntime(322):  at android.app.ActivityThread.main(ActivityThread.java:3683)
06-18 10:50:59.231: E/AndroidRuntime(322):  at java.lang.reflect.Method.invokeNative(Native Method)
06-18 10:50:59.231: E/AndroidRuntime(322):  at java.lang.reflect.Method.invoke(Method.java:507)
06-18 10:50:59.231: E/AndroidRuntime(322):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
06-18 10:50:59.231: E/AndroidRuntime(322):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
06-18 10:50:59.231: E/AndroidRuntime(322):  at dalvik.system.NativeStart.main(Native Method)

以下是图书馆的Link

2 个答案:

答案 0 :(得分:2)

我找到了解决方案,我必须有一个项目库,即appcompact v7添加到我的项目中,这解决了我的问题。

来源:Google

答案 1 :(得分:0)

这对我来说,构建apk时出现了问题,该类似乎没有在apk中打包,也试图避免将proguard作为第一个。