zoukankan      html  css  js  c++  java
  • android 实现圆形波纹动画

    在app中这种效果用的越来越多了,下面看看如何实现这种效果,这里我整理了两种实现这种效果的方式

    方式一:
    使用github上面的类库,把这个类库加入到我们的项目中即可
    https://github.com/ozodrukh/CircularReveal
    具体代码实现
     1 <?xml version="1.0" encoding="utf-8"?>
     2 <io.codetail.widget.RevealLinearLayout
     3     xmlns:android="http://schemas.android.com/apk/res/android"
     4     xmlns:tools="http://schemas.android.com/tools"
     5     android:layout_width="match_parent"
     6     android:layout_height="match_parent"
     7     tools:context="com.leyue100.fenjie.MainActivity">
     8 
     9     <LinearLayout
    10         android:id="@+id/ly"
    11         android:layout_width="match_parent"
    12         android:layout_height="match_parent"
    13         android:background="@color/my_blue"
    14         android:gravity="center"
    15         android:orientation="vertical">
    16         <ImageView
    17             android:id="@+id/image"
    18             android:layout_width="wrap_content"
    19             android:layout_height="wrap_content"
    20             android:layout_gravity="center"
    21             android:src="@mipmap/ic_launcher"
    22 
    23             />
    24 
    25     </LinearLayout>
    26 </io.codetail.widget.RevealLinearLayout>

    Activity设置动画

     1 package com.leyue100.fenjie;
     2 
     3 import android.os.Bundle;
     4 import android.support.v7.app.AppCompatActivity;
     5 import android.view.animation.AccelerateDecelerateInterpolator;
     6 import android.widget.ImageView;
     7 import android.widget.LinearLayout;
     8 
     9 import com.leyue100.fenjie.util.Util;
    10 
    11 import butterknife.Bind;
    12 import butterknife.ButterKnife;
    13 import io.codetail.animation.SupportAnimator;
    14 import io.codetail.animation.ViewAnimationUtils;
    15 
    16 public class MainActivity extends AppCompatActivity {
    17 
    18 
    19     @Bind(R.id.image)
    20     ImageView image;
    21     @Bind(R.id.ly)
    22     LinearLayout ly;
    23 
    24     private boolean hasAnimationStarted;
    25 
    26     @Override
    27     protected void onCreate(Bundle savedInstanceState) {
    28         super.onCreate(savedInstanceState);
    29         setContentView(R.layout.activity_main);
    30         ButterKnife.bind(this);
    31     }
    32 
    33     @Override
    34     public void onWindowFocusChanged(boolean hasFocus) {
    35         //控制动画显示一次
    36         if (hasFocus && !hasAnimationStarted) {
    37             startCircular();
    38         }
    39     }
    40 
    41     private void startCircular() {
    42         //获取图片所在屏幕的位置
    43         int[] location = new int[2];
    44         image.getLocationOnScreen(location);
    45         
    46         //设置圆的中心点
    47         int cx = location[0] + image.getWidth()/2;
    48         int cy = location[1] - image.getHeight()/2 - Util.dpToPx(24);
    49 
    50         int dx = Math.max(cx, ly.getWidth() - cx);
    51         int dy = Math.max(cy, ly.getHeight() - cy);
    52         //设置半径
    53         float finalRadius = (float) Math.hypot(dx, dy);
    54         SupportAnimator animator = ViewAnimationUtils.createCircularReveal(ly, cx, cy, 0, finalRadius);
    55         animator.setInterpolator(new AccelerateDecelerateInterpolator());
    56         animator.setDuration(3000);
    57         animator.start();
    58         hasAnimationStarted = true;
    59     }
    60 }

    使用第三方类很简单就可以实现出来

    下面介绍一种自己实现的方式

    自定义view 

    RevealBackgroundView

      1 package com.leyue100.lingwai.view;
      2 
      3 import android.animation.Animator;
      4 import android.animation.AnimatorListenerAdapter;
      5 import android.animation.ObjectAnimator;
      6 import android.content.Context;
      7 import android.graphics.Canvas;
      8 import android.graphics.Color;
      9 import android.graphics.Paint;
     10 import android.util.AttributeSet;
     11 import android.view.View;
     12 import android.view.animation.AccelerateDecelerateInterpolator;
     13 import android.view.animation.Interpolator;
     14 
     15 /**
     16  * Created by lihao on 16/2/18.
     17  * Version : 1.0
     18  * desc:
     19  */
     20 public class RevealBackgroundView extends View {
     21 
     22     //设置状态
     23     public static final int STATE_NOT_STARTED = 0;
     24     public static final int STATE_FILL_STARTED = 1;
     25     public static final int STATE_FINSHED = 3;
     26 
     27     private static final Interpolator INTERPOLATOR = new AccelerateDecelerateInterpolator();
     28     private static final int FILL_TIME = 4000;
     29 
     30     private int state = STATE_NOT_STARTED;
     31 
     32     private Paint fillPaint;
     33     private int currentRadius;
     34     private ObjectAnimator revealAnimator;
     35 
     36     private int startLocationX;
     37     private int startLocationY;
     38 
     39     private OnStateChangeListener onStateChangeListener;
     40 
     41 
     42     public RevealBackgroundView(Context context) {
     43         super(context);
     44         init();
     45     }
     46 
     47     public RevealBackgroundView(Context context, AttributeSet attrs) {
     48         super(context, attrs);
     49         init();
     50     }
     51 
     52     public RevealBackgroundView(Context context, AttributeSet attrs, int defStyleAttr) {
     53         super(context, attrs, defStyleAttr);
     54         init();
     55     }
     56 
     57     /**
     58      * 初始化数据
     59      */
     60     private void init() {
     61         fillPaint = new Paint(Paint.ANTI_ALIAS_FLAG|Paint.DITHER_FLAG);
     62         fillPaint.setStyle(Paint.Style.FILL);
     63         fillPaint.setColor(Color.WHITE);
     64     }
     65 
     66     public void setFillPaintColor(int color) {
     67         fillPaint.setColor(color);
     68     }
     69 
     70     public void startFromLocation(int[] tapLocationOnScreen) {
     71         //设置状态为开始
     72         changeState(STATE_FILL_STARTED);
     73         //获取到中心点即动画开始的位置
     74         startLocationX = tapLocationOnScreen[0];
     75         startLocationY = tapLocationOnScreen[1];
     76         //设置半径
     77         int finalRadius = (int) Math.hypot(getHeight(), getWidth());
     78         //设置动画 重点currentRadius设置动画的半径
     79         revealAnimator = ObjectAnimator.ofInt(this, "currentRadius", 0, finalRadius);
     80         revealAnimator.setInterpolator(INTERPOLATOR);
     81         revealAnimator.setDuration(FILL_TIME);
     82         revealAnimator.addListener(new AnimatorListenerAdapter() {
     83             @Override
     84             public void onAnimationEnd(Animator animation) {
     85                 super.onAnimationEnd(animation);
     86                 changeState(STATE_FINSHED);
     87             }
     88         });
     89         revealAnimator.start();
     90     }
     91 
     92     public void setToFinishedFrame() {
     93         changeState(STATE_FINSHED);
     94         invalidate();
     95     }
     96 
     97     @Override
     98     protected void onDraw(Canvas canvas) {
     99         if (state == STATE_FINSHED){
    100             //状态完成画一个矩形
    101             canvas.drawRect(0,0,getWidth(),getHeight(),fillPaint);
    102         } else {
    103             //画圆
    104             canvas.drawCircle(startLocationX,startLocationY,currentRadius,fillPaint);
    105         }
    106     }
    107 
    108     /**
    109      * 设置状态
    110      * @param state
    111      */
    112     private void changeState(int state) {
    113         if(this.state == state) {
    114             return;
    115         }
    116         this.state = state;
    117         if(onStateChangeListener != null) {
    118             onStateChangeListener.onStateChange(state);
    119         }
    120     }
    121 
    122     /**
    123      * 动画回调此方法
    124      * @param radius
    125      */
    126     public void setCurrentRadius(int radius) {
    127         this.currentRadius = radius;
    128         invalidate();
    129     }
    130 
    131     public void setOnStateChangeListener(OnStateChangeListener onStateChangeListener) {
    132         this.onStateChangeListener = onStateChangeListener;
    133     }
    134     public interface OnStateChangeListener{
    135         void onStateChange(int state);
    136     }
    137 }

    使用自定义控件:

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     3     xmlns:tools="http://schemas.android.com/tools"
     4     android:layout_width="match_parent"
     5     android:layout_height="match_parent"
     6     tools:context="com.leyue100.lingwai.MainActivity">
     7 
     8     <com.leyue100.lingwai.view.RevealBackgroundView
     9         android:id="@+id/backgroundView"
    10         android:layout_width="match_parent"
    11         android:layout_height="match_parent" />
    12     <ImageView
    13         android:id="@+id/image"
    14         android:layout_width="wrap_content"
    15         android:layout_height="wrap_content"
    16         android:layout_gravity="center"
    17         android:src="@mipmap/ic_launcher"
    18         android:layout_centerInParent="true"
    19         />
    20 </RelativeLayout>

    Activity中使用

    package com.leyue100.lingwai;
    
    import android.graphics.Color;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.view.ViewTreeObserver;
    import android.widget.ImageView;
    import android.widget.Toast;
    
    import com.leyue100.lingwai.view.RevealBackgroundView;
    
    import butterknife.Bind;
    import butterknife.ButterKnife;
    
    public class MainActivity extends AppCompatActivity {
    
        @Bind(R.id.backgroundView)
        RevealBackgroundView backgroundView;
        @Bind(R.id.image)
        ImageView image;
    
        private final static String TAG = "MainActivity";
        private boolean hasAnimationStarted;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ButterKnife.bind(this);
        }
    
        @Override
        public void onWindowFocusChanged(boolean hasFocus) {
            if (hasFocus && !hasAnimationStarted) {
                setupRevaalBackground();
            }
    
        }
    
        public void setupRevaalBackground() {
            backgroundView.setOnStateChangeListener(new RevealBackgroundView.OnStateChangeListener() {
                @Override
                public void onStateChange(int state) {
                    if (state == RevealBackgroundView.STATE_FINSHED) {
                        Toast.makeText(MainActivity.this, "动画结束", Toast.LENGTH_SHORT).show();
                    }
                }
            });
            
            //获取动画开始位置
            final int[] location = new int[2];
            image.getLocationOnScreen(location);
            
            //启动动画
            backgroundView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                    backgroundView.getViewTreeObserver().removeOnPreDrawListener(this);
                    backgroundView.setFillPaintColor(Color.parseColor("#2196F3"));
                    backgroundView.startFromLocation(location);
                    hasAnimationStarted = true;
                    return true;
    
                }
            });
    
        }
    }

    这两种方式做起来都很简单

  • 相关阅读:
    Error[e46]: Undefined external "?V1" referred in AF
    总是遇到奇怪问题一
    BrokenPipeError: [Errno 32] Broken pipe
    Segment BANKED_CODE must be defined in a segment definition option (-Z, -b or -P)
    使用jupyter打开已存在的ipynb文件
    时钟控制命令
    中断系统以及外部中断
    pytorch上的循环层和全连接层操作
    02池化层
    距离毕业还有---100天
  • 原文地址:https://www.cnblogs.com/lihaolihao/p/5200883.html
Copyright © 2011-2022 走看看