Advanced view animation in Android

2020-06-07 05:04发布

问题:

I'm developing an app for Android with beautiful, but hard-to-implement design with tons of custom animations. Now I need to implement animation for button, it must be dynamic glance animation that affects both button border and its text, and must move from left to right. Here is an example of such animation in iOS app.

So I hope you catched the main idea. I tried to use Property Animation, but it's not what I really need. Also I found many custom libraries and tried a lot of examples from SDK, but there are nothing similar.

So if you know how it can be do, answer me.

回答1:

try this wrapper class:

class FL extends FrameLayout implements ValueAnimator.AnimatorUpdateListener {
    private static final int W = 200;
    private final LinearGradient gradient;
    private final Paint paint;
    private float x;

    public FL(View child) {
        super(child.getContext());
        addView(child);
        int[] colors = {0, 0xaaffffff, 0};
        gradient = new LinearGradient(0, 0, W, 0, colors, null, Shader.TileMode.CLAMP);
        paint = new Paint();
        paint.setShader(gradient);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
        x = -W;
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        canvas.saveLayer(null, null, 0);
        super.dispatchDraw(canvas);
        canvas.translate(x, 0);
        float h = getHeight();
        canvas.rotate(20, W / 2, h / 2);
        canvas.drawRect(0, -h, W, 2 * h, paint);
        canvas.restore();
    }

    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        x = (int) animation.getAnimatedValue();
        invalidate();
    }

    public void startMagic() {
        ValueAnimator a = ValueAnimator.ofInt(-W, getWidth());
        a.addUpdateListener(this);
        a.setDuration(1000).setInterpolator(new AccelerateDecelerateInterpolator());
        a.start();
    }
}

round_frame.xml is:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="20dp" />
    <stroke android:color="#a00" android:width="4dp" />
</shape>

and test it with the following in onCreate:

    Button b = new Button(this);
    final FL fl = new FL(b);
    b.setTextSize(28);
    b.setTextColor(0xffaa0000);
    b.setText("click me to see the magic");
    b.setBackgroundResource(R.drawable.round_frame);
    View.OnClickListener listener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            fl.startMagic();
        }
    };
    b.setOnClickListener(listener);
    addContentView(fl, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));

NOTE: if you want it to use it in the Button only, you don't have a FL wrapper: you can extend Button class and override drawing methods as i did in FL wrapper class



回答2:

I get the pre-rendered animation with a sequence of PNG files and then use the AnimationDrawable to display it.



回答3:

I finished my custom implementation of this.

The result so far :

This is obtained by transferring an animated gradient Shader on the static TextView You can get the source code on the following Gist : ShinnyTextView

The current version does not support XML customization, but you can adapt the values in the code.

If you are using this, you might want to have a more precise control on when to pause/restart the animation to avoid the ani