Is it possible to have an animated drawable?

后端 未结 7 1097
野的像风
野的像风 2020-12-28 10:34

Is it possible to create a drawable that has some sort of animation, whether it is a frame by frame animation, rotation, etc, that is defined as a xml drawable and can be re

7条回答
  •  鱼传尺愫
    2020-12-28 10:50

    Yes! The (undocumented) key, which I discovered by reading the ProgressBar code is that you have to call Drawable.setLevel() in onDraw() in order for the thing to have any effect. The ProgressBar works something like this (extra unimportant code omitted):

    The drawable XML:

    
        
            
        
        
            
        
    
    

    In onDraw():

        Drawable d = getDrawable();
        if (d != null)
        {
            // Translate canvas so a indeterminate circular progress bar with
            // padding rotates properly in its animation
            canvas.save();
            canvas.translate(getPaddingLeft(), getPaddingTop());
    
            long time = getDrawingTime();
    
            // I'm not sure about the +1.
            float prog = (float)(time % ANIM_PERIOD+1) / (float)ANIM_PERIOD; 
            int level = (int)(MAX_LEVEL * prog);
            d.setLevel(level);
            d.draw(canvas);
    
            canvas.restore();
    
            ViewCompat.postInvalidateOnAnimation(this);
        }
    

    MAX_LEVEL is a constant, and is always 10000 (according to the docs). ANIM_PERIOD is the period of your animation in milliseconds.

    Unfortunately since you need to modify onDraw() you can't just put this drawable in an ImageView since ImageView never changes the drawable level. However you may be able to change the drawable level from outside the ImageView's. ProgressBar (ab)uses an AlphaAnimation to set the level. So you'd do something like this:

    mMyImageView.setImageDrawable(myDrawable);
    
    ObjectAnimator anim = ObjectAnimator.ofInt(myDrawable, "level", 0, MAX_LEVEL);
    anim.setRepeatCount(ObjectAnimator.INFINITE);
    anim.start();
    

    It might work but I haven't tested it.

    Edit

    There is actually an ImageView.setImageLevel() method so it might be as simple as:

    ObjectAnimator anim = ObjectAnimator.ofInt(myImageVew, "ImageLevel", 0, MAX_LEVEL);
    anim.setRepeatCount(ObjectAnimator.INFINITE);
    anim.start();
    

提交回复
热议问题