如何解决Material Design中android ripple效果果和onTouch事件的冲突

问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
注:ide是ADT23
很喜欢Material Design 的Ripple波纹效果
创建项目的时候
Minimum Required SDK 选择API 11: Android 3.0
就这样,这样的话各种按钮什么的控件都有水波纹效果
然而把Minimum Required SDK选择API 14: Android 4.0
却没了这种效果,小白完全不知道为什么T.T
就是这种效果:
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
试了下,表示两种情况都要包裹在com.andexert.library.RippleView之中才有效果。
测试机器是4.4的
用的android studio 1.3
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
因为这种特性支持在Android5.0的设备.而想兼容低系统版本的话,就需要新建v21(即Android5.0)的Resource Directory.
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
这个和3.0和4.0没有关系.波纹效果是5.0以后加的.如果想要在更早的版本使用,需要使用依赖库来实现.喜欢Material design的话,可以看看谷歌自己出的design support library.
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
google的design support library.在API 21以下是没有Ripple效果的,想要在低版本实现涟漪效果的话,就的用第三方类库了。
同步到新浪微博
分享到微博?
Hi,欢迎来到 SegmentFault 技术社区!⊙▽⊙ 在这里,你可以提出编程相关的疑惑,关注感兴趣的问题,对认可的回答投赞同票;大家会帮你解决编程的问题,和你探讨技术更新,为你的回答投上赞同票。
明天提醒我
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
扫扫下载 AppAndroid MaterialDesign之水波点击效果的几种实现方法 - 简书
Android MaterialDesign之水波点击效果的几种实现方法
什么是水波点击的效果? 下面是几种不同的实现方法的效果图以及实现方法
Video__003846
如何实现?
方法一 使用官方提供的RippleDrawable类
优点:使用方便,非常漂亮。
缺点:Android5.0以下版本无法使用
添加一个普通的 ripple_bg_drawable.xml 背景文件
&?xml version="1.0" encoding="utf-8"?&
&shape xmlns:android="/apk/res/android"
android:shape="rectangle"&
&solid android:color="#8cc476" /&
&corners android:radius="0dp" /&
添加带波纹效果的背景文件 ripple_bg.xml
&?xml version="1.0" encoding="utf-8"?&
&ripple xmlns:android="/apk/res/android"
android:color="#FF21272B"&
&item android:drawable="@drawable/ripple_bg_drawable" /&
这里使用了上面的xml文件作为背景,然后给组件设置背景时,选 ripple_bg.xml 就可以了。如
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="@drawable/ripple_bg"
android:padding="10dp"
android:text="使用RippleDrawable类实现" /&
Video__231558
很简单的录制了下gif ,质量不好。实际效果很好看。
注意事项:如果你的api最低版本低于21,则ripple这里其实是有错误提醒的,低于这个版本会报错。
方法二 使用代码实现
优点:低版本兼容、使用简单
缺点:效果不如官方的好
在values下添加 attrs.xml 文件
&?xml version="1.0" encoding="utf-8"?&
&resources&
&declare-styleable name="MaterialLayout"&
&attr name="alpha" format="integer" /&
&attr name="alpha_step" format="integer" /&
&attr name="framerate" format="integer" /&
&attr name="duration" format="integer" /&
&attr name="mycolor" format="color" /&
&attr name="scale" format="float" /&
&/declare-styleable&
&/resources&
添加一个自定义的布局类 MaterialLayout.class
public class MaterialLayout extends RelativeLayout {
private static final int DEFAULT_RADIUS = 10;
private static final int DEFAULT_FRAME_RATE = 10;
private static final int DEFAULT_DURATION = 200;
private static final int DEFAULT_ALPHA = 255;
private static final float DEFAULT_SCALE = 0.8f;
private static final int DEFAULT_ALPHA_STEP = 5;
* 动画帧率
private int mFrameRate = DEFAULT_FRAME_RATE;
* 渐变动画持续时间
private int mDuration = DEFAULT_DURATION;
private Paint mPaint = new Paint();
* 被点击的视图的中心点
private Point mCenterPoint =
* 视图的Rect
private RectF mTargetR
* 起始的圆形背景半径
private int mRadius = DEFAULT_RADIUS;
* 最大的半径
private int mMaxRadius = DEFAULT_RADIUS;
* 渐变的背景色
private int mCirclelColor = Color.LTGRAY;
* 每次重绘时半径的增幅
private int mRadiusStep = 1;
* 保存用户设置的alpha值
private int mBackupA
* 圆形半径针对于被点击视图的缩放比例,默认为0.8
private float mCircleScale = DEFAULT_SCALE;
* 颜色的alpha值, (0, 255)
private int mColorAlpha = DEFAULT_ALPHA;
* 每次动画Alpha的渐变递减值
private int mAlphaStep = DEFAULT_ALPHA_STEP;
private View mTargetV
* @param context
public MaterialLayout(Context context) {
this(context, null);
public MaterialLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
public MaterialLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
private void init(Context context, AttributeSet attrs) {
if (isInEditMode()) {
if (attrs != null) {
initTypedArray(context, attrs);
initPaint();
this.setWillNotDraw(false);
this.setDrawingCacheEnabled(true);
private void initTypedArray(Context context, AttributeSet attrs) {
final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MaterialLayout);
mCirclelColor = typedArray.getColor(R.styleable.MaterialLayout_mycolor, Color.LTGRAY);
mDuration = typedArray.getInteger(R.styleable.MaterialLayout_duration, DEFAULT_DURATION);
mFrameRate = typedArray.getInteger(R.styleable.MaterialLayout_framerate, DEFAULT_FRAME_RATE);
mColorAlpha = typedArray.getInteger(R.styleable.MaterialLayout_alpha, DEFAULT_ALPHA);
mCircleScale = typedArray.getFloat(R.styleable.MaterialLayout_scale, DEFAULT_SCALE);
typedArray.recycle();
private void initPaint() {
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(mCirclelColor);
mPaint.setAlpha(mColorAlpha);
// 备份alpha属性用于动画完成时重置
mBackupAlpha = mColorA
* 点击的某个坐标点是否在View的内部
* @param touchView
* @param x 被点击的x坐标
* @param y 被点击的y坐标
* @return 如果点击的坐标在该view内则返回true,否则返回false
private boolean isInFrame(View touchView, float x, float y) {
initViewRect(touchView);
return mTargetRectf.contains(x, y);
* 获取点中的区域,屏幕绝对坐标值,这个高度值也包含了状态栏和标题栏高度
* @param touchView
private void initViewRect(View touchView) {
int[] location = new int[2];
touchView.getLocationOnScreen(location);
// 视图的区域
mTargetRectf = new RectF(location[0], location[1], location[0] + touchView.getWidth(),
location[1] + touchView.getHeight());
* 减去状态栏和标题栏的高度
private void removeExtraHeight() {
int[] location = new int[2];
this.getLocationOnScreen(location);
// 减去两个该布局的top,这个top值就是状态栏的高度
mTargetRectf.top -= location[1];
mTargetRectf.bottom -= location[1];
// 计算中心点坐标
int centerHorizontal = (int) (mTargetRectf.left + mTargetRectf.right) / 2;
int centerVertical = (int) ((mTargetRectf.top + mTargetRectf.bottom) / 2);
// 获取中心点
mCenterPoint = new Point(centerHorizontal, centerVertical);
private View findTargetView(ViewGroup viewGroup, float x, float y) {
int childCount = viewGroup.getChildCount();
// 迭代查找被点击的目标视图
for (int i = 0; i & childC i++) {
View childView = viewGroup.getChildAt(i);
if (childView instanceof ViewGroup) {
return findTargetView((ViewGroup) childView, x, y);
} else if (isInFrame(childView, x, y)) { // 否则判断该点是否在该View的frame内
return childV
private boolean isAnimEnd() {
return mRadius &= mMaxR
private void calculateMaxRadius(View view) {
// 取视图的最长边
int maxLength = Math.max(view.getWidth(), view.getHeight());
// 计算Ripple圆形的半径
mMaxRadius = (int) ((maxLength / 2) * mCircleScale);
int redrawCount = mDuration / mFrameR
// 计算每次动画半径的增值
mRadiusStep = (mMaxRadius - DEFAULT_RADIUS) / redrawC
// 计算每次alpha递减的值
mAlphaStep = (mColorAlpha - 100) / redrawC
* 处理ACTION_DOWN触摸事件, 注意这里获取的是Raw x, y,
* 即屏幕的绝对坐标,但是这个当屏幕中有状态栏和标题栏时就需要去掉这些高度,因此得到mTargetRectf后其高度需要减去该布局的top起点
* ,也就是标题栏和状态栏的总高度.
* @param event
private void deliveryTouchDownEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mTargetView = findTargetView(this, event.getRawX(), event.getRawY());
if (mTargetView != null) {
removeExtraHeight();
// 计算相关数据
calculateMaxRadius(mTargetView);
// 重绘视图
invalidate();
public boolean onInterceptTouchEvent(MotionEvent event) {
deliveryTouchDownEvent(event);
return super.onInterceptTouchEvent(event);
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
// 绘制Circle
drawRippleIfNecessary(canvas);
private void drawRippleIfNecessary(Canvas canvas) {
if (isFoundTouchedSubView()) {
// 计算新的半径和alpha值
mRadius += mRadiusS
mColorAlpha -= mAlphaS
// 裁剪一块区域,这块区域就是被点击的View的区域.通过clipRect来获取这块区域,使得绘制操作只能在这个区域范围内的进行,
// 即使绘制的内容大于这块区域,那么大于这块区域的绘制内容将不可见. 这样保证了背景层只能绘制在被点击的视图的区域
canvas.clipRect(mTargetRectf);
mPaint.setAlpha(mColorAlpha);
// 绘制背景圆形,也就是
canvas.drawCircle(mCenterPoint.x, mCenterPoint.y, mRadius, mPaint);
if (isAnimEnd()) {
invalidateDelayed();
* 发送重绘消息
private void invalidateDelayed() {
this.postDelayed(new Runnable() {
public void run() {
invalidate();
}, mFrameRate);
* 判断是否找到被点击的子视图
private boolean isFoundTouchedSubView() {
return mCenterPoint != null && mTargetView !=
private void reset() {
mCenterPoint =
mTargetRectf =
mRadius = DEFAULT_RADIUS;
mColorAlpha = mBackupA
mTargetView =
invalidate();
在布局文件中引用
&com.liangddyy.rippledemo.MaterialLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"&
&LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"&
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="100dp"
android:padding="10dp"
android:text="自定义布局实现1" /&
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="100dp"
android:padding="10dp"
android:text="自定义布局实现2" /&
&/LinearLayout&
&/com.liangddyy.rippledemo.MaterialLayout&
Video__235950
其实可以看到,只要在 MaterialLayout 布局中的控件都有这个效果,所以使用其他是很方便的。
这部分代码见原作者博客
方法三 第三方库实现
github上的一个叫
优点:美观、使用简单、最低兼容API 9
缺点:不如官方的好看啦
dependencies {
compile 'com.github.traex.rippleeffect:library:1.3'
使用类似于方法二,比较灵活和方便
&com.andexert.library.RippleView
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="100dp"
rv_centered="true"&
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#4ce65e"
android:text="第三方库实现"/&
&/com.andexert.library.RippleView&
如果直接导入使用报错,那可以复制如下源码到工程使用。
定义个颜色
&color name="rippelColor"&#FFFFFF&/color&
添加attrs.xml
&?xml version="1.0" encoding="utf-8"?&
&resources&
&declare-styleable name="RippleView"&
&attr name="rv_alpha" format="integer" /&
&attr name="rv_framerate" format="integer" /&
&attr name="rv_rippleDuration" format="integer" /&
&attr name="rv_zoomDuration" format="integer" /&
&attr name="rv_color" format="color" /&
&attr name="rv_centered" format="boolean" /&
&attr name="rv_type" format="enum"&
&enum name="simpleRipple" value="0" /&
&enum name="doubleRipple" value="1" /&
&enum name="rectangle" value="2" /&
&attr name="rv_ripplePadding" format="dimension" /&
&attr name="rv_zoom" format="boolean" /&
&attr name="rv_zoomScale" format="float" /&
&/declare-styleable&
&/resources&
添加RippleView.java文件
代码太多,不复制了。参见末尾处的项目源码吧。
Video__003808
最后附上整个示例工程代码:
我的博客原文:直接拿来用!十大Material Design开源项目
发表于 18:19|
作者唐小引
摘要:本文详细介绍了十个Material Design开源项目,从示例、FAB、菜单、动画、Ripple到Dialog,看被誉为“Google第一次在设计语言和规范上超越了Apple”的Material Design是如何逐渐成为App的一种全新设计标准。
介于拟物和扁平之间的Material Design自面世以来,便引起了很多人的关注与思考,就此产生的讨论也不绝于耳。本文详细介绍了在Android开发者圈子里颇受青睐的十个Material Design开源项目,从示例、FAB、菜单、动画、Ripple到Dialog,看被称为“Google第一次在设计语言和规范上超越了Apple”的Material Design是如何逐渐成为App的一种全新设计标准。1. 在众多新晋库中,MaterialDesignLibrary可以说是颇受开发者瞩目的一个控件效果库,能够让开发者在Android 2.2系统上使用Android 5.0才支持的控件效果,比如扁平、矩形、浮动按钮,复选框以及各式各样的进度指示器等。除上述之外,MaterialDesignLibrary还拥有SnackBar、Dialog、Color selector组件,可非常便捷地对应用界面进行设置。进度指示器样式效果设置:&com.gc.materialdesign.views.ProgressBarCircularIndetermininate
android:id="@+id/progressBarCircularIndetermininate"
android:layout_width="32dp"
android:layout_height="32dp"
android:background="#1E88E5" /&Dialog:Dialog dialog = new Dialog(Context context,String title, String message);
dialog.show();相关链接:2. 由来自法兰西的Robin Chutaux开发的RippleEffect基于MIT许可协议开源,能够在Android API 9+上实现Material Design,为开发者提供了一种极为简易的方式来创建带有可扩展视图的header视图,并且允许最大程度上的自定制。用法(在XML文件中声明一个RippleView):&com.andexert.library.RippleView
android:id="@+id/more"
android:layout_width="?android:actionBarSize"
android:layout_height="?android:actionBarSize"
android:layout_toLeftOf="@+id/more2"
android:layout_margin="5dp"
ripple:rv_centered="true"&
&ImageView
android:layout_width="?android:actionBarSize"
android:layout_height="?android:actionBarSize"
android:src="@android:drawable/ic_menu_edit"
android:layout_centerInParent="true"
android:padding="10dp"
android:background="@android:color/holo_blue_dark"/&
&/com.andexert.library.RippleView&相关链接:3. 随着Material Design的到来,AppCompat v21也为开发者提供了Material Design的控件外观支持,其中就包括EditText,但却并不好用,没有设置颜色的API,也没有任何Google Material Design Spec中提到的特性。于是,来自国内的开发者“扔物线”开发了MaterialEditText库,直接继承EditText,无需修改Java文件即能实现自定义控件颜色。自定义Base Color:app:baseColor="#0056d3"自定义Error Color:app:maxCharacters="10"
app:errorColor="#ddaa00"相关链接:4. Android-LollipopShowcase是由来自奥地利的移动、后端及Web开发者Mike Penz所开发的演示应用,集中演示了新Material Design中所有的UI效果,以及Android Lollipop中其他非常酷炫的特性元素,比如Toolbar、RecyclerView、ActionBarDrawerToggle、Floating Action Button(FAB)、Android Compat Theme等。相关链接:5. MaterialList是一个能够帮助所有Android开发者获取谷歌UI设计规范中新增的CardView(卡片视图)的开源库,支持Android 2.3+系统。作为ListView的扩展,MaterialList可以接收、存储卡片列表,并根据它们的Android风格和设计模式进行展示。此外,开发者还可以创建专属于自己的卡片布局,并轻松将其添加到CardList中。
推荐阅读相关主题:
CSDN官方微信
扫描二维码,向CSDN吐槽
微信号:CSDNnews
相关热门文章

我要回帖

更多关于 ripple钱包 的文章

 

随机推荐