Android 5.0水波纹效果

Android 按钮实现按压水波纹效果 方法一: 在控件中加入android:foreground="?selectableItemBackground" 即可实现水波纹的效果。 但是这需要在API23 也就是说需要在Android6.0系统的手机上面,才会有效果。 方法二: 给Button按钮设置背景 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 阅读详情

前言
上篇博客已经是很久以前了,这段时间的确是忙了很多,技术相关的也做的少了。近期一个项目中,需要在4.4上实现一些5.0上的特效,例如Button之类的控件点击时的水波纹效果。在blog里找到了任教主的一篇博文,受到了启发,将他的Demo改动了一些就实现了。具体在应用到自己项目中时遇到了些需求变化和其他问题,这里就相当于做一个记录。

效果演示
AS还是不怎么会用,gif的图就没有了,这里给个静态的
这里写图片描述
这里说明一下,这个截图是一个拨号盘,在拨号的时候会有水波纹效果。

对比Demo中的效果
![这里写图片描述](https://img-blog.youkuaiyun.com/20150729171157159)

从效果图中可以看出与其他水波纹Demo的差异之处在于这个水波纹可以突破控件自身的大小。

思路
重载dispatchTouchEvent获取相应的坐标以及绘制对象,
重载dispatchDraw,根据点击事件来绘制一个逐渐变大的Circle。

代码及说明
Java代码

 public class CustomTableLayout extends TableLayout{

    private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Paint mBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

    /**目标控件宽度*/
    private int mTargetWidth;

    /**目标控件高度*/
    private int mTargetHeight;

    /**最小高宽*/
    private int mMinBetweenWidthAndHeight;
    private int mMaxBetweenWidthAndHeight;

    /**水波纹最大半径*/
    private int mMaxRevealRadius;

    /**水波纹半径增量*/
    private int mRevealRadiusGap;

    /**水波纹半径*/
    private int mRevealRadius = 0;

    /**布局处于屏幕的坐标*/
    private int[] mLocationInScreen = new int[2];

    /**是否绘制水波纹*/
    private boolean mShouldDoAnimation = false;

    /**点击状态*/
    private boolean mIsPressed = false;

    /**绘制间隔*/
    private int INVALIDATE_DURATION = 40;

    /**点击的View*/
    private View mTouchTarget;

    public CustomTableLayout(Context context) {
        super(context);
        init();
    }

    public CustomTableLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        setWillNotDraw(false);
        mPaint.setColor(getResources().getColor(R.color.reveal_color_2));
        mBgPaint.setColor(getResources().getColor(R.color.reveal_color_2));
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        this.getLocationOnScreen(mLocationInScreen);
    }

    /**
     * @Title: initParametersForChildNew   
     * @Description: 初始化各个参数   
     * @param: @param view
     * @return: void      
     * @throws
     */
    private void initParametersForChildNew(View view){
        mTargetWidth = view.getMeasuredWidth();
        mTargetHeight = view.getMeasuredHeight();
        mMinBetweenWidthAndHeight = Math.min(mTargetWidth, mTargetHeight);
        mMaxBetweenWidthAndHeight = Math.max(mTargetWidth, mTargetHeight);
        mRevealRadius = 0;
        mShouldDoAnimation = true;
        mIsPressed = true;
        mRevealRadiusGap = mMinBetweenWidthAndHeight / 8;

        int[] location = new int[2];
        view.getLocationOnScreen(location);

        //突破控件大小的关键之一
        mMaxRevealRadius = mMaxBetweenWidthAndHeight/4 +2*mRevealRadiusGap;
    }

    /**
     * @Title: getTouchTarget   
     * @Description: 获取点击的View   
     * @param: @param view
     * @param: @param x
     * @param: @param y
     * @param: @return
     * @return: View      
     * @throws
     */
    private View getTouchTarget(View view, int x, int y) {
        View target = null;
        ArrayList<View> TouchableViews = view.getTouchables();
        for (View child : TouchableViews) {
            if (isTouchPointInView(child, x, y)) {
                target = child;
                break;
            }
        }
        return target;
    }

    /**
     * @Title: isTouchPointInView   
     * @Description: 判断point是否是处于View中  
     * @param: @param view
     * @param: @param x
     * @param: @param y
     * @param: @return
     * @return: boolean      
     * @throws
     */
    private boolean isTouchPointInView(View view, int x, int y) {
        int[] location = new int[2];
        view.getLocationOnScreen(location);
        int left = location[0];
        int top = location[1];
        int right = left + view.getMeasuredWidth();
        int bottom = top + view.getMeasuredHeight();
        if (view.isClickable() && y >= top && y <= bottom
                && x >= left && x <= right) {
            return true;
        }
        return false;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
         int x = (int) event.getRawX();
            int y = (int) event.getRawY();
            int action = event.getAction();
            if (action == MotionEvent.ACTION_DOWN) {
                View touchTarget = getTouchTarget(this, x, y);
                if (touchTarget != null && touchTarget.isClickable() && touchTarget.isEnabled()) {
                    mTouchTarget = touchTarget;
                    initParametersForChildNew(touchTarget);
                    postInvalidateDelayed(INVALIDATE_DURATION);
                }
            } else if (action == MotionEvent.ACTION_UP) {
                mIsPressed = false;
                postInvalidateDelayed(INVALIDATE_DURATION*2);
            } else if (action == MotionEvent.ACTION_CANCEL) {
                mIsPressed = false;
                postInvalidateDelayed(INVALIDATE_DURATION);
            }

        return super.dispatchTouchEvent(event);
    }


    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);

         if (!mShouldDoAnimation || mTargetWidth <= 0 || mTouchTarget == null) {
                return;
            }

            if (mRevealRadius > mMaxRevealRadius) {

            } else {
                mRevealRadius += mRevealRadiusGap;
            }
            this.getLocationOnScreen(mLocationInScreen);
            int[] location = new int[2];
            mTouchTarget.getLocationOnScreen(location);
            int left = location[0] - mLocationInScreen[0];
            int top = location[1] - mLocationInScreen[1];
            int right = left + mTouchTarget.getMeasuredWidth();
            int bottom = top + mTouchTarget.getMeasuredHeight();
            canvas.save();
            canvas.clipRect(left, top-mRevealRadius, right, bottom+mRevealRadius);
            canvas.drawCircle(left+mTargetWidth/2, top+mTargetHeight/2, mMaxRevealRadius, mBgPaint);
            canvas.drawCircle(left+mTargetWidth/2, top+mTargetHeight/2, mRevealRadius, mPaint);
            canvas.restore();

            if (mRevealRadius <= mMaxRevealRadius) {
                postInvalidateDelayed(INVALIDATE_DURATION, left, top-mMaxRevealRadius, right, bottom+mMaxRevealRadius);
            } else if (!mIsPressed) {
                mShouldDoAnimation = false;
                postInvalidateDelayed(INVALIDATE_DURATION, left, top-mMaxRevealRadius, right, bottom+mMaxRevealRadius);
            }
    }
} 

我这继承的是一个TabLayout,当然也可以继承其他的Layout实现相同效果。
由于是要做一个扩散出来的水波纹,这里的circle就的圆心就取的是死的,没有根据event来获取,需求不一致就需要重新计算canvas.drawCircle(left+mTargetWidth/2, top+mTargetHeight/2, mRevealRadius, mPaint);和postInvalidateDelayed(INVALIDATE_DURATION, left, top-mMaxRevealRadius, right, bottom+mMaxRevealRadius);

最后有几个需要提醒的地方是,dispatchTouchEvent中最好只return super.dispatchTouchEvent(event);
否则可能会出现长按事件混淆的问题。

用AI科研绘图全新升级!借助谷歌新发布模型Nano Banana pro实测一键绘制机制图与技术路线图,直接告别文字乱码与低画质 之前有同仁反馈,用Nano Banana画科研插图的时候,要么文字部分容易乱码,要么抓不住关键内容,画出来的效果反复修改后,还是达不到理想的效果。终于在Gemini 3发布没几天,万众期待的大香蕉模型也成功升级到了Pro版本,官方名称叫“Gemini 3 Pro Image”,实际上也就是我们说的Nano Banana 2。这次的Nano Banana Pro模型,不仅可以直出4K高清图,还能自定义比例,推理能力和中文文字的稳定性也得到了提升。 阅读详情

相关推荐

知识导航神器:Obsidian Breadcrumbs 插件全攻略

Parent: 插件Child: Breadcrumbs 用法这样,它就能识别出你和其他笔记的关系。

m0_73735578的博客 1629

android 说话水波动画,android中波浪效果的实现

在Android的一些app中,经常有一些水波纹的加载效果,非常好看,比如下面的为知笔记的加载效果就是非常的好看~~还有一些加速球等等中的波浪效果也是类似。那么应该怎么实现这种效果呢?我们从效果上看,这个效果大概可以分为两个难点。绘制波浪图形让波浪随时间荡漾起来1.分析先说第一个,如何绘制波浪图形。绘制波浪图形的方法有很多,这里介绍一种最简单的方法,就是使用canvas的drawLine方法绘制直...

weixin_35318343的博客 945

Claude Code vs Codex

Claude Code 提供了一个生产就绪(production-ready)的实现,包含良好的错误处理、优雅的关闭逻辑、详细注释和文档,以及内置测试。Claude Code 输出了一个可运行的 Next.js + TypeScript 前端,但错过了一些设计里的黄色主题元素;Codex 则生成自己的版本,没有导出设计中的图片,也没严格遵照设计主题。Codex 完成同样功能,但更简洁直接,文档和注释少一些但功能达标。任务都用同样的提示,使用 TypeScript 实现,并在一天内完成。

weixin_49869937的博客 2386

android录音波浪动画_Android语音输入的波浪效果 – WaveView

效果展示源码地址实现思路绘制正弦波形水平移动波形,即可得到破浪效果。正弦波形的绘制private void createShader() {...Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(bitmap);// Dra...

weixin_39611546的博客 2312

深入RK3588内存管理:如何用dma_buf_alloc和mpp_buffer为RGA2分配4G以内内存(附kernel版本选择)

本文深入探讨了RK3588平台上RGA2核心的4G内存限制问题,详细解析了dma_buf_alloc和mpp_buffer两种内存分配方案的技术细节与适用场景。通过代码示例和性能对比,帮助开发者优化高分辨率视频处理流程,并提供了内核版本选择与常见错误排查指南。

weixin_29168153的博客 364

【SOC 芯片设计 DFT 学习专栏 -- DFT DRC规则检查】

在现代半导体设计中,DFT(Design for Test)技术的重要性不言而喻。它确保了芯片在制造完成后能够进行高效和可靠的测试。DFT设计规则检查(DRC)作为DFT流程中的一个关键环节,通过一系列自动化工具检测设计中的潜在问题,从而保证设计的可测试性和整体质量。在本文中,我们将详细探讨DFT DRC的概念、重要性、检查流程以及具体的规则和应用。Tessent是业界领先的DFT解决方案之一,其DRC工具通过一系列自动化检查,确保设计符合DFT要求。

CodingCos的博客 4167

Android5.0适配——水波纹点击效果

Android5.0后默认的的点击效果带有高大上的水波纹,但是如果你还是按照5.0前那样设置背景的话那就不会有波纹,实现也超级简单一,先在res文件夹下新建一个drawable-v21文件夹二,把我们5.0之前的背景文件比如select或者shape等复制到这drawable-v21文件夹下比如我之前是这样一个selector :&lt;selector xmlns:android="http:/...

u012156512的博客 1万+

数据中心——Vxlan基本概念1

东西流量指的就是横向流量-------例如:服务器与服务器之间交换流量南北流量指的就是纵向流量-------例如:客户端和服务器之间的流量以下主要是讲解业务平面的网络架构(一般业务平面就需要用到专用的数据中心交换机)

m0_49864110的博客 1万+

聊聊Android5.0中的水波纹效果

水波纹效果已经不是什么稀罕的东西了,用过5.0新控件的小伙伴都知道这个效果,可是如果使用一个TextView或者Button或者其它普通控件的话,你是否知道如何给它设置水波纹效果呢?OK,我们今天就来看看这个水波纹效果的实现。水波纹效果的实现有系统自带属性可以实现,我们也可以自定义实现效果。1.系统自带水波纹实现方式有界水波纹水波纹效果大致上可以分为两种,一种是有界的,一种无界,我们先来看看...

weixin_30417487的博客 532

078、镜头阴影校正:LSC算法原理与标定优化

文章摘要 镜头阴影校正(LSC)是手机影像系统中的关键技术,用于解决镜头渐晕效应导致的画面边缘暗角问题。本文详细分析了LSC算法的核心原理,包括非均匀网格划分、双线性插值等关键技术点,并揭示了标定流程中的常见陷阱(光源均匀性、灰卡反射特性、温度漂移)。文章还深入探讨了增益计算的工程实现细节,以及实际调优中的关键考量因素(色差校正、动态场景适应等)。作者结合15年经验,给出了包括验证方法、网格参数设计、产线标定等实用性建议,强调LSC算法应与光学设计协同优化,才能达到最佳效果。

sundong_81的博客 42

SAP ABAP Append structure 介绍

所有在 append structure 上增强的字段都是 append structure 的一部分,这意味着对这些增强所做的任何更改仅仅施加在 append structure 上,而不会影响被增强的 ABAP DDIC 结构。这同样适用于 transport. 激活数据库表或结构时,会找到所有关联的 append structure,并将它们的组件附加到数据库表或结构。Append structure(附加结构)是 ABAP 字典中附加到另一个结构或数据库表并将其组件附加到它们的结构。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1165

基于安卓5.0水波纹效果制作及自定义水波纹颜色

安卓5.0以后很多ui效果的改进都是为提高用户体验,其中水波纹效果是5.0以后是在交互方式中做的特殊处理 接下来学习一下水波纹的简单使用及水波纹颜色的自定义。 首先布局文件中给控件设置为可点击,及背景的添加 xml version="1.0" encoding="utf-8"?>LinearLayout xmlns:android="http://schemas.

qq_30587885的博客 1425

面向精准医疗的多模态影像融合:实现前列腺MRI与大病理切片的三维配准与空间重建研究

亲爱的同学,当你能完整实现“前列腺MRI与大病理组织学图像的3D配准及体素重建”,你会发现医学影像交叉领域的毕设课题充满挑战与乐趣。我们将从临床需求出发,拆解3D配准与体素重建的核心技术,带你从原理到代码实现完整流程,让你的毕设不仅能顺利完成,更能体现临床应用价值。,让MRI和病理图像在同一空间对齐,能实现“术前影像-术后病理”的精准关联,为前列腺癌的精准诊疗、预后评估提供关键依据——这一课题既有技术挑战性,又有临床意义,是毕设的优质选择。(如NCC、Dice、配准时间),用数据证明方法的优越性。

m0_71589036的博客 4717

android5.0 给View添加水波纹效果

Android 5.0以上超出边界圆形水波纹 android:background="?android:attr/actionBarItemBackground" Android 5.0以上超出边界内圆形水波纹 android:background="?android:attr/selectableItemBackground" 版权声明:本文为优快云博主「Hello_Lnjy」的原创文章,遵循...

qq_38287890的博客 187

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Android5.0特性 - 水波纹效果、揭示效果

看了几篇文章,文章所言要实现水波纹的效果需要最小编译版本为21,之前我只是认为5.0之后,手机会自带水波纹,明显有些错误Effect :build :minSdkVersion 21if (minSdkVersion 21 = true){ can user ripple }如上所诉sdk21之后,可以使用ripple,而ripple便是实现水波纹的一个关键,我们在drawable 创建

Android、前端、小程序、后端 2679

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

(转)Android5.0适配——水波纹点击效果

原地址: Android5.0后默认的的点击效果带有高大上的水波纹,但是如果你还是按照5.0前那样设置背景的话那就不会有波纹,实现也超级简单 一,先在res文件夹下新建一个drawable-v21文件夹 二,把我们5.0之前的背景文件比如select或者shape等复制到这drawable-v21文件夹下 比如我之前是这样一个select

Elvis写代码 745

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

android 水波纹效果button_Android 5.0 Button 按钮水纹效果的适配问题

从5.0开始,一些控件的点击时候默认是有水纹效果的如下图这里写图片描述以Button举例可以按照如下使用:注意是android:themeandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Button"android:theme="@style/MyButton"/>自定义...

weixin_34858011的博客 246

android5.0水波纹效果

原文链接   http://blog.csdn.net/u012702547/article/details/52325418  侵删 水波纹效果已经不是什么稀罕的东西了,用过5.0新控件的小伙伴都知道这个效果,可是如果使用一个TextView或者Button或者其它普通控件的话,你是否知道如何给它设置水波纹效果呢?OK,我们今天就来看看这个水波纹效果的实现。水波纹效果的实现有系

lk_0x00的博客 324

android 5.0以上版本控件点击 水波纹效果

android api21及以上引入了控件点击的水波纹效果 1.可以直接给空间设置 android:background="?android:attr/selectableItemBackground"(有边界效果) 或者  android:backgroundTint="?android:attr/selectableItemBackgroundBorderl

qq_35017727的博客 6883

Android5.0水波纹点击效果

是API21才有的新Tag,正是实现水波纹效果的; 其中这个是指定水波纹的颜色.

Z873499451的博客 384

安卓5.0水波纹效果及自定义属性

&lt;TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="16dp"android:layout_marginTop="16dp"android:background="?android:attr/selectableItemBackgr...

梦想不只是梦与想的博客 237

Android 水波纹点击效果(Ripple Effect)

本文介绍的是Android5.0中其中一个炫酷的效果,点击水波纹扩散效果(Ripple Effect). 以下介绍的实现方式都是调用Android5.0的新API,并非自定义实现,所以只支持在Android5.0及以上的设备. 而大家想兼容低系统版本的话,就需要新建v21(即Android5.0)的Resource Directory. 效果如下图所示:

cxcbupt 6801

Android 点击水波纹扩散效果( Ripple Effect )

文章转载自:http://www.tuicool.com/articles/NFr6jie 以下介绍的实现方式都是调用Android5.0的新API,并非自定义实现,所以支持在Android5.0的设备. 而大家想兼容低系统版本的话,就需要新建v21(即Android5.0)的Resource Directory. 圆角背景的水波纹效果(如上图) 1. 定义一个普通圆角

用尽悲伤的专栏 5209

安卓5.0及以上设置水波纹效果

一般的可以点击的条目(listView,RecyclerView…),直接设置背景选择器, 选择器颜色,默认白色,点击灰色,当然根据你的情况自己设置: 为了适配5.0需要在drawable-v21里写另外一个ripple(如下:) 例外:对于不是可以点击的linearLayout等,需要你额外设置可点击和焦点,android:focusable="true" android:cli

forLove 917

Android5.0水波纹效果适配4.X

最近研究Google Material Design 发现档次比公司UI图高很多,有木有.这里先实现个水波纹效果来感受下 效果图: 1. 系统有界效果.xml设置:android:background="?android:attr/selectableItemBackground"向下兼容,API21以下也可以使用,点击会变色,但不会有水波纹效果.2. 系统无界效果.xml设置:android:b

HeDongDong的博客 2895
上一篇: Android 悬浮框实现
下一篇: Android USB相关广播的使用
HelloKen
博客等级 码龄17年 7粉丝 10原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值