美文网首页新视频开发动画
3.Android 抖音直播头像动画 头像动效缩放特效

3.Android 抖音直播头像动画 头像动效缩放特效

作者: 鹏城十八少 | 来源:发表于2021-06-17 22:58 被阅读0次

    动画描述:

    1.绘制圆形头像

    2.头像图片缩小然后放大到远处(心跳动画)

    3.头像缩小的同时,画一个和头像一样的圈,圈放大,透明度变化。(外面的圆圈向外扩散)

    原理分析:

    valueAnimator+invalidate()

    方法二:

    1.已经有了圆形头像。想通过组合的形式

    继承Relalayouy.然后把原型图片位置放我,然后绘制一个外圆。

    这样是不靠谱的,因为继承RelativeLayout不会再去实现ondraw方法。而是dispathDraw方法。!

    方法三:

    1.因为头像和圈是同一个控件,所以不能直接操作view

    一直改变绘制头像的半径。导致图像缩放

    小圆和大圆的中心点不变,变的只是半径!

    2.扩散效果:再绘制一个圆,变大它的半径和透明度。

    备注:

    不能操作view就用这个valueAnimator。配合自定义绘制

    ObjectAnimator:完全操控view

    public class RoundImageViewextends AppCompatImageView {

    private int borderColor;// 圆形头像的边框颜色

        private int borderWidth;// 圆形头像的边框宽度

        private PaintmBitmapPaint;// 绘制图像的Paint

        private PaintmBorderPaint;

        private MatrixmMatrix;// 图像矩阵,本身是一个3*3矩阵

        private int mRadius;

        private int mImgWidth;

        private int centerX;

        private int centerY;

        /***

    *

        * @param context

        * @param attrs

        */

        private float smallInnerScaleRatio =1f;//变小

        private float BigOutsideRatio =1f;

        public RoundImageView(Context context, AttributeSet attrs) {

    this(context, attrs, 0);

        }

    public RoundImageView(Context context) {

    this(context, null);

        }

    public RoundImageView(Context context, AttributeSet attrs, int defStyleAttr) {

    super(context, attrs, defStyleAttr);

            initAttrs(context, attrs);

            mBitmapPaint =new Paint();

            mBorderPaint =new Paint();

            mMatrix =new Matrix();

            mBitmapPaint.setAntiAlias(true);

            mBorderPaint.setAntiAlias(true);

        }

    private void initAttrs(Context context, AttributeSet attrs) {

    borderColor = Color.RED;

            borderWidth =8;

            postDelayed(new Runnable() {

    @Override

                public void run() {

    startAnim();

                }

    }, 2000);

        }

    private void startAnim() {

    ValueAnimator valueAnimator = ValueAnimator.ofFloat(1f, 0.5f);

            valueAnimator.setInterpolator(new LinearInterpolator());

            valueAnimator.setDuration(500);

            valueAnimator.setRepeatCount(-1);

            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

    @Override

                public void onAnimationUpdate(ValueAnimator animation) {

    float value = (float) animation.getAnimatedValue();

                    smallInnerScaleRatio = value;

                    BigOutsideRatio =1 + (1 - value);

                    invalidate();

                }

    });

            valueAnimator.start();

        }

    @Override

        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

    //写好一个控件自定义View,写出一个能用的自定义View不易啊。。。

            // 虽然测量这块儿寥寥几行代码,但是还得心细啊。。

            int imgHeight = setMeasureHeight(heightMeasureSpec) - getPaddingTop() - getPaddingBottom() -borderWidth *2;

            int imgWidth = setMeasureWidth(widthMeasureSpec) - getPaddingLeft() - getPaddingRight() -borderWidth *2;

            if (imgHeight < imgWidth) {

    mImgWidth = imgHeight;

                mRadius =mImgWidth /2;

                centerX =mRadius;

                centerY =mRadius;

                Log.d("Round", "imgHeight < imgWidth");

            }else {//

                mImgWidth = imgWidth;

                mRadius =mImgWidth /4;//半径是图片的一半

                centerX =mImgWidth /2;

                centerY =centerX;

                Log.d("Round", "imgHeight > imgWidth");

            }

    setMeasuredDimension(setMeasureWidth(widthMeasureSpec), setMeasureHeight(heightMeasureSpec));

        }

    private int setMeasureHeight(int heightMeasureSpec) {

    int height =0;

            int minHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 56,

                    getResources().getDisplayMetrics());

            int specMode = MeasureSpec.getMode(heightMeasureSpec);

            int specSize = MeasureSpec.getSize(heightMeasureSpec);

            switch (specMode) {

    case MeasureSpec.EXACTLY:

    height = (specSize < minHeight ? minHeight : specSize);// 此处我是设置了EXACTLY的值,仅是圆形图片大小的值

                    break;

                case MeasureSpec.AT_MOST:

    height = minHeight + getPaddingTop() + getPaddingBottom();

    break;

                case MeasureSpec.UNSPECIFIED:

    height = minHeight + getPaddingTop() + getPaddingBottom();

    break;

            }

    return height;

        }

    private int setMeasureWidth(int widthMeasureSpec) {

    int width =0;

            int minWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 56,

                    getResources().getDisplayMetrics());

            int specMode = MeasureSpec.getMode(widthMeasureSpec);

            int specSize = MeasureSpec.getSize(widthMeasureSpec);

            switch (specMode) {

    case MeasureSpec.EXACTLY:

    width = (specSize < minWidth ? minWidth : specSize);

    break;

                case MeasureSpec.AT_MOST:

    width = minWidth + getPaddingLeft() + getPaddingRight();

    break;

                case MeasureSpec.UNSPECIFIED:

    width = minWidth + getPaddingRight() + getPaddingLeft();

    break;

            }

    return width;

        }

    @Override

        protected void onDraw(Canvas canvas) {

    this.setBackgroundColor(Color.WHITE);

            if (getDrawable() ==null) {

    return;

            }

    setShader();

            float realRadiusBitmap =mRadius *smallInnerScaleRatio;//修改图片绘制的半径,而缩放

            //中心点

            float centerTempx =centerX +borderWidth + getPaddingLeft();

            float centerTempy =centerY +borderWidth + getPaddingTop();

            canvas.drawCircle(centerTempx, centerTempy,

                    realRadiusBitmap, mBitmapPaint);//绘制头像

            mBorderPaint.setColor(borderColor);

            mBorderPaint.setStyle(Paint.Style.STROKE);

            mBorderPaint.setStrokeWidth(borderWidth /2);

            canvas.drawCircle(centerX +borderWidth + getPaddingLeft(), centerY +borderWidth + getPaddingTop(),

                    mRadius +borderWidth /2, mBorderPaint);//绘制外圆

            float realRadiusOut =mRadius *BigOutsideRatio;

            mBorderPaint.setStrokeWidth(borderWidth /2);

            mBorderPaint.setColor(Color.GREEN);

            canvas.drawCircle(centerX +borderWidth + getPaddingLeft(), centerY +borderWidth + getPaddingTop(),

                    realRadiusOut +borderWidth /2, mBorderPaint);//绘制散动的圆

        }

    /**

        * 初始化bitmapShader

        * 图片缩放,通过矩阵进行。

        * 在于矩阵先缩放,再移动

        */

        private void setShader() {

    Drawable drawable = getDrawable();

            Bitmap bmp = drawableToBitmap(drawable);

            BitmapShader mBitmapShader =new BitmapShader(bmp, TileMode.CLAMP, TileMode.CLAMP);

            float scale =1.0f;

            // 去取bitmap中宽度和高度中更小的,为了使图像缩放之后,可以填充满控件的空间,

            // 此处切记要乘以1.0f,,这种低级错误写的时候又犯了一次。

            scale =mImgWidth *1.0f / (Math.min(bmp.getWidth(), bmp.getHeight()));

    //        scale=scale*currentScaleRatio;

            mMatrix.setScale(scale, scale);

            mMatrix.postTranslate(getPaddingLeft() +borderWidth, getPaddingTop() +borderWidth);//这里使用了Matrix的后乘进行效果叠加,

            // 使图像根据padding进行位移

            mBitmapShader.setLocalMatrix(mMatrix);

            mBitmapPaint.setShader(mBitmapShader);

        }

    /**

        * 将Drawable转变为bitmap

    */

        private BitmapdrawableToBitmap(Drawable drawable) {

    if (drawableinstanceof BitmapDrawable) {

    BitmapDrawable bd = (BitmapDrawable) drawable;

                return bd.getBitmap();

            }

    int h = drawable.getIntrinsicHeight();

            int w = drawable.getIntrinsicWidth();

            Bitmap bitmap = Bitmap.createBitmap(w, h, Config.ARGB_8888);

            Canvas canvas =new Canvas(bitmap);// 建立对应的bitmap画布

            drawable.setBounds(0, 0, w, h);// 此处的setBounds是指,drawable将在canvas的0,0,w,h矩形区域内

            drawable.draw(canvas);// 将drawable的内容画到画布中去

            return bitmap;

        }

    }

    android 抖音头像缩放

    https://blog.csdn.net/sange77/article/details/102597074

    https://www.jianshu.com/p/daa6e2710e1c

    动画效果:先放大,然后回到原来的效果

    https://blog.csdn.net/u010632547/article/details/107204254/

    相关文章

      网友评论

        本文标题:3.Android 抖音直播头像动画 头像动效缩放特效

        本文链接:https://www.haomeiwen.com/subject/skuhyltx.html