美文网首页
仿Android的呼吸动画

仿Android的呼吸动画

作者: gqs已经存在 | 来源:发表于2020-05-23 18:08 被阅读0次

    前言

    简单模仿了下Android的呼吸动画,实现比较简单,很多细节还可以调整,另外如果动画更复杂,建议直接通过lottie实现。

    实现

    继承FramLayout 创建一个动画类,代码如下

    
    public class AvatarFrame extends FrameLayout {
    
        private float cx;
    
        private float cy;
    
        private float mStartRadius;
    
        private float outsideRadius;
    
        private float middleRadius;
    
        private float insideRadius;
    
        private Paint outsidePaint;
    
        private Paint middlePaint;
    
        private Paint insidePaint;
    
        private Paint strokePaint;
    
        private float layerWidth;
    
        private float strokeWidth;
    
        private float extraWidth;
    
        public AvatarFrame(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    
            super(context, attrs, defStyleAttr);
    
            init();
    
        }
    
        public AvatarFrame(@NonNull Context context, @Nullable AttributeSet attrs) {
    
            this(context, attrs,0);
    
        }
    
        public AvatarFrame(@NonNull Context context) {
    
            this(context,null);
    
        }
    
        private void init(){
    
            setWillNotDraw(false);
    
            strokeWidth = convertDpToPx(3);
    
            strokePaint = new Paint();
    
            strokePaint.setAntiAlias(true);
    
            strokePaint.setStrokeWidth(convertDpToPx(3));
    
            strokePaint.setStyle(Paint.Style.STROKE);
    
            strokePaint.setColor(Color.BLUE);
    
            outsidePaint = new Paint();
    
            outsidePaint.setAntiAlias(true);
    
            outsidePaint.setColor(Color.parseColor("#FF5B26"));
    
            outsidePaint.setAlpha(76);
    
            middlePaint = new Paint();
    
            middlePaint.setAntiAlias(true);
    
            middlePaint.setColor(Color.RED);
    
            middlePaint.setAlpha(140);
    
            insidePaint = new Paint();
    
            insidePaint.setAntiAlias(true);
    
            insidePaint.setColor(Color.parseColor("#FF5B26"));
    
            insidePaint.setAlpha(76);
    
        }
    
        @Override
    
        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    
            super.onLayout(changed, left, top, right, bottom);
    
            cx = (float) getWidth()/2;
    
            cy = (float)getHeight()/2;
    
            extraWidth = getPaddingLeft() - strokeWidth;
    
            layerWidth = extraWidth / 3;
    
            mStartRadius =  (float) getWidth()/2 - extraWidth;
    
        }
    
        @Override
    
        protected void onDraw(Canvas canvas) {
    
            if(!isClear){
    
                canvas.drawCircle(cx,cy,insideRadius,insidePaint);
    
                canvas.drawCircle(cx,cy,middleRadius,middlePaint);
    
                canvas.drawCircle(cx,cy,outsideRadius,outsidePaint);
    
                canvas.drawCircle(cx,cy,mStartRadius - strokeWidth ,strokePaint);
    
            }
    
            super.onDraw(canvas);
    
        }
    
        private void update(float percent){
    
            isClear = false;
    
            outsideRadius = mStartRadius + (extraWidth * percent);
    
            middleRadius = mStartRadius  + ((extraWidth - layerWidth) * percent);
    
            insideRadius = mStartRadius + ((extraWidth - layerWidth * 2) * percent);
    
            invalidate();
    
        }
    
        boolean isClear;
    
        private void clear(){
    
            isClear = true;
    
            invalidate();
    
        }
    
        public void stopAnim(){
    
            if(animator != null && animator.isRunning()){
    
                animator.cancel();
    
            }
    
            clear();
    
        }
    
        private ValueAnimator animator;
    
        public void startAnim(){
    
            animator = ValueAnimator.ofFloat(0,1f);
    
            animator.setDuration(500);
    
            animator.setRepeatMode(ValueAnimator.REVERSE);
    
            animator.setRepeatCount(-1);
    
            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    
                @Override
    
                public void onAnimationUpdate(ValueAnimator animation) {
    
                    float percent = (float) animation.getAnimatedValue();
    
                    update(percent);
    
                }
    
            });
    
            animator.start();
    
        }
    
        public float  convertDpToPx(float dp){
    
            return (getDefaultDisplayMetrics().density * dp );
    
        }
    
        public  DisplayMetrics getDefaultDisplayMetrics(){
    
            return getResources().getDisplayMetrics();
    
        }
    
    

    使用

    
    <?xml version="1.0" encoding="utf-8"?>
    
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    
        xmlns:app="http://schemas.android.com/apk/res-auto"
    
        xmlns:tools="http://schemas.android.com/tools"
    
        android:layout_width="match_parent"
    
        android:layout_height="match_parent"
    
        android:orientation="vertical"
    
        android:gravity="center_horizontal"
    
        tools:context=".MainActivity">
    
        <Button
    
            android:layout_width="wrap_content"
    
            android:layout_height="wrap_content"
    
            android:layout_marginTop="50dp"
    
            android:text="play"
    
            android:id="@+id/btnPlay"/>
    
        <Button
    
            android:layout_width="wrap_content"
    
            android:layout_height="wrap_content"
    
            android:layout_marginTop="50dp"
    
            android:text="Stop"
    
            android:id="@+id/btnStop"/>
    
        <com.gg.AvatarFrame
    
            android:layout_gravity="center"
    
            android:layout_marginTop="50dp"
    
            android:layout_width="wrap_content"
    
            android:layout_height="wrap_content"
    
            android:padding="12dp"
    
            android:id="@+id/fm_avatar">
    
            <ImageView
    
                android:layout_width="120dp"
    
                android:layout_height="120dp"
    
                android:background="@drawable/bg_frame"
    
                android:id="@+id/ivImage"
    
                />
    
        </com.gqs.androidtest.AvatarFrame>
    
    </LinearLayout>
    
    
    
    mAvatarFrame = findViewById(R.id.fm_avatar);
    
            Button button = findViewById(R.id.btnPlay);
    
            Button btnStop = findViewById(R.id.btnStop);
    
            btnStop.setOnClickListener(new View.OnClickListener() {
    
                @Override
    
                public void onClick(View v) {
    
                    mAvatarFrame.stopAnim();
    
                }
    
            });
    
            button.setOnClickListener(new View.OnClickListener() {
    
                @Override
    
                public void onClick(View v) {
    
                    mAvatarFrame.startAnim();
    
                }
    
            });
    
    

    基本就是这样,代码很简单,就不过多介绍了

    相关文章

      网友评论

          本文标题:仿Android的呼吸动画

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