zoukankan      html  css  js  c++  java
  • 在Android中实现来自Material设计的Ripple效果:RippleEffect

    网络示例图:

    RippleView.java

      1 /*
      2  * The MIT License (MIT)
      3  *
      4  * Copyright (c) 2014 Robin Chutaux
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a copy
      7  * of this software and associated documentation files (the "Software"), to deal
      8  * in the Software without restriction, including without limitation the rights
      9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10  * copies of the Software, and to permit persons to whom the Software is
     11  * furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22  * THE SOFTWARE.
     23  */
     24 
     25 package com.maomao.beautymovie.widget;
     26 
     27 
     28 import com.maomao.beautymovie.R;
     29 
     30 import android.content.Context;
     31 import android.content.res.TypedArray;
     32 import android.graphics.Bitmap;
     33 import android.graphics.Canvas;
     34 import android.graphics.Paint;
     35 import android.graphics.PorterDuff;
     36 import android.graphics.PorterDuffXfermode;
     37 import android.graphics.Rect;
     38 import android.os.Handler;
     39 import android.util.AttributeSet;
     40 import android.view.GestureDetector;
     41 import android.view.MotionEvent;
     42 import android.view.View;
     43 import android.view.ViewGroup;
     44 import android.view.animation.Animation;
     45 import android.view.animation.ScaleAnimation;
     46 import android.widget.RelativeLayout;
     47 
     48 /**
     49  * Author :    Chutaux Robin
     50  * Date :      10/8/2014
     51  */
     52 public class RippleView extends RelativeLayout
     53 {
     54     private int WIDTH;
     55     private int HEIGHT;
     56     private int FRAME_RATE = 10;
     57     private int DURATION = 400;
     58     private int PAINT_ALPHA = 90;
     59     private Handler canvasHandler;
     60     private float radiusMax = 0;
     61     private boolean animationRunning = false;
     62     private int timer = 0;
     63     private int timerEmpty = 0;
     64     private int durationEmpty = -1;
     65     private float x = -1;
     66     private float y = -1;
     67     private int zoomDuration;
     68     private float zoomScale;
     69     private ScaleAnimation scaleAnimation;
     70     private Boolean hasToZoom;
     71     private Boolean isCentered;
     72     private Integer rippleType;
     73     private Paint paint;
     74     private Bitmap originBitmap;
     75     private int rippleColor;
     76     private View childView;
     77     private int ripplePadding;
     78     private GestureDetector gestureDetector;
     79     private Runnable runnable = new Runnable()
     80     {
     81         @Override
     82         public void run()
     83         {
     84             invalidate();
     85         }
     86     };
     87 
     88     public RippleView(Context context)
     89     {
     90         super(context);
     91     }
     92 
     93     public RippleView(Context context, AttributeSet attrs)
     94     {
     95         super(context, attrs);
     96         init(context, attrs);
     97     }
     98 
     99     public RippleView(Context context, AttributeSet attrs, int defStyle)
    100     {
    101         super(context, attrs, defStyle);
    102         init(context, attrs);
    103     }
    104 
    105     private void init(final Context context, final AttributeSet attrs)
    106     {
    107         if (isInEditMode())
    108             return;
    109 
    110         final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RippleView);
    111         rippleColor = typedArray.getColor(R.styleable.RippleView_rv_color, getResources().getColor(R.color.rippelColor));
    112         rippleType = typedArray.getInt(R.styleable.RippleView_rv_type, 0);
    113         hasToZoom = typedArray.getBoolean(R.styleable.RippleView_rv_zoom, false);
    114         isCentered = typedArray.getBoolean(R.styleable.RippleView_rv_centered, false);
    115         DURATION = typedArray.getInteger(R.styleable.RippleView_rv_rippleDuration, DURATION);
    116         FRAME_RATE = typedArray.getInteger(R.styleable.RippleView_rv_framerate, FRAME_RATE);
    117         PAINT_ALPHA = typedArray.getInteger(R.styleable.RippleView_rv_alpha, PAINT_ALPHA);
    118         ripplePadding = typedArray.getDimensionPixelSize(R.styleable.RippleView_rv_ripplePadding, 0);
    119         canvasHandler = new Handler();
    120         zoomScale = typedArray.getFloat(R.styleable.RippleView_rv_zoomScale, 1.03f);
    121         zoomDuration = typedArray.getInt(R.styleable.RippleView_rv_zoomDuration, 200);
    122         paint = new Paint();
    123         paint.setAntiAlias(true);
    124         paint.setStyle(Paint.Style.FILL);
    125         paint.setColor(rippleColor);
    126         paint.setAlpha(PAINT_ALPHA);
    127         this.setWillNotDraw(false);
    128 
    129         gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener()
    130         {
    131             @Override
    132             public boolean onSingleTapConfirmed(MotionEvent e)
    133             {
    134                 return true;
    135             }
    136 
    137             @Override
    138             public boolean onSingleTapUp(MotionEvent e)
    139             {
    140                 return true;
    141             }
    142         });
    143 
    144         this.setDrawingCacheEnabled(true);
    145     }
    146 
    147     @Override
    148     public void addView(View child, int index, ViewGroup.LayoutParams params)
    149     {
    150         childView = child;
    151         super.addView(child, index, params);
    152     }
    153 
    154     @Override
    155     public void draw(Canvas canvas)
    156     {
    157         super.draw(canvas);
    158         if (animationRunning)
    159         {
    160             if (DURATION <= timer * FRAME_RATE)
    161             {
    162                 animationRunning = false;
    163                 timer = 0;
    164                 durationEmpty = -1;
    165                 timerEmpty = 0;
    166                 canvas.restore();
    167                 invalidate();
    168                 return;
    169             }
    170             else
    171                 canvasHandler.postDelayed(runnable, FRAME_RATE);
    172 
    173             if (timer == 0)
    174                 canvas.save();
    175 
    176 
    177             canvas.drawCircle(x, y, (radiusMax * (((float) timer * FRAME_RATE) / DURATION)), paint);
    178 
    179             paint.setColor(getResources().getColor(android.R.color.holo_red_light));
    180 
    181             if (rippleType == 1 && originBitmap != null && (((float) timer * FRAME_RATE) / DURATION) > 0.4f)
    182             {
    183                 if (durationEmpty == -1)
    184                     durationEmpty = DURATION - timer * FRAME_RATE;
    185 
    186                 timerEmpty++;
    187                 final Bitmap tmpBitmap = getCircleBitmap((int) ((radiusMax) * (((float) timerEmpty * FRAME_RATE) / (durationEmpty))));
    188                 canvas.drawBitmap(tmpBitmap, 0, 0, paint);
    189                 tmpBitmap.recycle();
    190             }
    191 
    192             paint.setColor(rippleColor);
    193 
    194             if (rippleType == 1)
    195             {
    196                 if ((((float) timer * FRAME_RATE) / DURATION) > 0.6f)
    197                     paint.setAlpha((int) (PAINT_ALPHA - ((PAINT_ALPHA) * (((float) timerEmpty * FRAME_RATE) / (durationEmpty)))));
    198                 else
    199                     paint.setAlpha(PAINT_ALPHA);
    200             }
    201             else
    202                 paint.setAlpha((int) (PAINT_ALPHA - ((PAINT_ALPHA) * (((float) timer * FRAME_RATE) / DURATION))));
    203 
    204             timer++;
    205         }
    206     }
    207 
    208     @Override
    209     protected void onSizeChanged(int w, int h, int oldw, int oldh)
    210     {
    211         super.onSizeChanged(w, h, oldw, oldh);
    212         WIDTH = w;
    213         HEIGHT = h;
    214 
    215         scaleAnimation = new ScaleAnimation(1.0f, zoomScale, 1.0f, zoomScale, w / 2, h / 2);
    216         scaleAnimation.setDuration(zoomDuration);
    217         scaleAnimation.setRepeatMode(Animation.REVERSE);
    218         scaleAnimation.setRepeatCount(1);
    219     }
    220 
    221     @Override
    222     public boolean onTouchEvent(MotionEvent event)
    223     {
    224         if (gestureDetector.onTouchEvent(event) && !animationRunning)
    225         {
    226             if (hasToZoom)
    227                 this.startAnimation(scaleAnimation);
    228 
    229             radiusMax = Math.max(WIDTH, HEIGHT);
    230 
    231             if (rippleType != 2)
    232                 radiusMax /= 2;
    233 
    234             radiusMax -= ripplePadding;
    235 
    236             if (isCentered || rippleType == 1)
    237             {
    238                 this.x = getMeasuredWidth() / 2;
    239                 this.y = getMeasuredHeight() / 2;
    240             }
    241             else
    242             {
    243                 this.x = event.getX();
    244                 this.y = event.getY();
    245             }
    246 
    247             animationRunning = true;
    248 
    249             if (rippleType == 1 && originBitmap == null)
    250                 originBitmap = getDrawingCache(true);
    251 
    252             invalidate();
    253             this.performClick();
    254         }
    255 
    256         childView.onTouchEvent(event);
    257         return true;
    258     }
    259 
    260     @Override
    261     public boolean onInterceptTouchEvent(MotionEvent event)
    262     {
    263        return true;
    264     }
    265 
    266     private Bitmap getCircleBitmap(final int radius) {
    267         final Bitmap output = Bitmap.createBitmap(originBitmap.getWidth(), originBitmap.getHeight(), Bitmap.Config.ARGB_8888);
    268         final Canvas canvas = new Canvas(output);
    269         final Paint paint = new Paint();
    270         final Rect rect = new Rect((int)(x - radius), (int)(y - radius), (int)(x + radius), (int)(y + radius));
    271 
    272         paint.setAntiAlias(true);
    273         canvas.drawARGB(0, 0, 0, 0);
    274         canvas.drawCircle(x, y, radius, paint);
    275 
    276         paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    277         canvas.drawBitmap(originBitmap, rect, rect, paint);
    278 
    279         return output;
    280     }
    281 }
    View Code

    xml中声明:

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <LinearLayout android:orientation="vertical" 
     3     android:padding="5.0dip" 
     4     android:fitsSystemWindows="true" 
     5     android:clipToPadding="true" 
     6     android:layout_width="fill_parent" 
     7     android:layout_height="fill_parent"
     8     xmlns:android="http://schemas.android.com/apk/res/android"
     9     xmlns:ripple="http://schemas.android.com/apk/res-auto"
    10     xmlns:tools="http://schemas.android.com/tools"
    11     tools:context=".MainActivity">
    12     <EditText 
    13         android:textSize="16.0sp" 
    14         android:id="@+id/edit_email" 
    15         android:layout_width="fill_parent" 
    16         android:layout_height="wrap_content" 
    17         android:layout_marginTop="10.0dip" 
    18         android:hint="您的邮箱(选填)" 
    19         android:singleLine="true" />
    20     <EditText 
    21         android:textSize="16.0sp" 
    22         android:id="@+id/edit_advice" 
    23         android:layout_width="fill_parent" 
    24         android:layout_height="wrap_content" 
    25         android:layout_marginTop="20.0dip" 
    26         android:hint="您的意见或建议" />
    27 
    28    
    29     
    30         <com.maomao.beautymovie.widget.RippleView
    31         android:id="@+id/rect"
    32         android:layout_width="fill_parent"
    33         android:layout_marginTop="20dp"
    34         android:layout_marginLeft="10dp"
    35         android:layout_marginRight="10dp"
    36         android:layout_height="wrap_content"
    37         ripple:rv_type="rectangle"
    38         ripple:rv_zoom="true">
    39 
    40         <TextView
    41             android:id="@+id/rect_child"
    42             android:layout_width="fill_parent"
    43             android:layout_height="50dp"
    44             android:layout_centerInParent="true"
    45             android:textColor="@android:color/white"
    46             android:textSize="20sp"
    47             android:gravity="center"
    48             android:text="提交"
    49             android:background="@android:color/holo_blue_light"/>
    50 
    51     </com.maomao.beautymovie.widget.RippleView>
    52     
    53     
    54     
    55 </LinearLayout>

    activity中监听使用:

     1 package com.maomao.beautymovie;
     2 
     3 
     4 
     5 import com.maomao.beautymovie.widget.RippleView;
     6 
     7 
     8 public class FeedbackActivity extends BaseActivity {
     9 
    10     @Override
    11     protected void onCreate(Bundle savedInstanceState) {
    12         super.onCreate(savedInstanceState);
    13         setContentView(R.layout.activity_feedback);
    14         final RippleView rippleView = (RippleView) findViewById(R.id.rect);
    15 
    16         rippleView.setOnClickListener(new View.OnClickListener()
    17         {
    18             @Override
    19             public void onClick(View v)
    20             {
    21                 Toast.makeText(FeedbackActivity.this, "这是一个Toast提示", Toast.LENGTH_LONG).show();
    22             }
    23         });
    24  
    25             
    26     }
    27 
    28     @Override
    29     public boolean onOptionsItemSelected(MenuItem item) {
    30         if (item.getItemId() == android.R.id.home) {
    31             finish();
    32             return true;
    33         }
    34         return super.onOptionsItemSelected(item);
    35     }
    36 
    37 
    38 
    39 }

    demo:链接: http://pan.baidu.com/s/1i3zPZoD 密码: 96cz

  • 相关阅读:
    java.lang.NoSuchMethodError:antlr.collections.AST.getLine() I
    T7 java Web day01 标签HTML
    T6 s1 day19
    T5 s5 Day18
    T5 s4 Day 17
    T5 s3 day16
    T5 s2 Day 15
    T5 s1 day14
    T4 S03 day 12
    T4 S01 day1
  • 原文地址:https://www.cnblogs.com/ning1121/p/4378375.html
Copyright © 2011-2022 走看看