Android App开发之图像加工中给图像添加水波动态特效(附源码和演示视频 简单易懂)

简介: Android App开发之图像加工中给图像添加水波动态特效(附源码和演示视频 简单易懂)

需要图片集和源码请点赞关注收藏后评论区留言~~~

一、给图像添加水波特效

除了给图片添加静态装饰物,有时还想添加动态的特效,比如说水波涟漪特效。水波特效要求一个同心圆持续向外扩散,圆圈在数秒之内从圆心扩散到视图边缘,从而实现了涟漪扩散动画,这个持续扩散的操作可通过定时机制来实现,简单地说,结合处理器工具Handler与任务工具Runnable由处理器对象定时执行刷新任务即可完成水波动画。

视频如下 也可前往我的主页观看

水波动画

效果图如下  如果读者觉得水波变化速度太快,可以自行调整水波的扩散速度,具体在widget包下的RippleImageView类中修改 修改里面的postDealyed里面的参数时间即可

public void run() {
            mRadius += mIncrease;
            if (mRadius*mRadius > (mWidth*mWidth/4 + mHeight*mHeight/4)) { // 水波半径已超出对角线
                mRadius = 0;
                mIncrease = Utils.dip2px(mContext, 5);
            } else { // 水波半径未超出对角线
                mIncrease += Utils.dip2px(mContext, 1);
                mHandler.postDelayed(this, 500); // 延迟50毫秒后再次启动水波刷新任务
            }
            postInvalidate(); // 立即刷新视图(线程安全方式)
        }
    };

 

代码如下

Java主类

package com.example.picture;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import com.example.picture.widget.RippleImageView;
public class ImageRippleActivity extends AppCompatActivity {
    private RippleImageView riv_scene; // 声明一个水波图像对象
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_image_ripple);
        riv_scene = findViewById(R.id.riv_scene);
        riv_scene.setOnClickListener(v -> riv_scene.startRipple());
        initRippleSpinner(); // 初始化水波特效下拉框
    }
    // 初始化水波特效下拉框
    private void initRippleSpinner() {
        ArrayAdapter<String> rippleAdapter = new ArrayAdapter<>(this,
                R.layout.item_select, rippleNameArray);
        Spinner sp_ripple = findViewById(R.id.sp_ripple);
        sp_ripple.setPrompt("请选择水波特效");
        sp_ripple.setAdapter(rippleAdapter);
        sp_ripple.setOnItemSelectedListener(new RippleSelectedListener());
        sp_ripple.setSelection(0);
    }
    private String[] rippleNameArray = {"白色", "红色", "绿色", "蓝色", "黄色", "青色", "紫色"};
    private int[] rippleColoArray = {0x99ffffff, 0x99ff0000, 0x9900ff00, 0x990000ff, 0x99ffff00, 0x9900ffff, 0x99ff00ff};
    class RippleSelectedListener implements AdapterView.OnItemSelectedListener {
        public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
            riv_scene.setRippleColor(rippleColoArray[arg2]); // 设置水波的颜色
            riv_scene.startRipple(); // 开始播放水波动画
        }
        public void onNothingSelected(AdapterView<?> arg0) {}
    }
}

RipperImageView类

package com.example.picture.widget;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
import android.widget.ImageView;
import com.example.picture.util.Utils;
public class RippleImageView extends ImageView {
    private Context mContext; // 声明一个上下文对象
    private Paint mPaint = new Paint(); // 声明一个画笔对象
    private int mWidth, mHeight; // 视图宽度、视图高度
    private int mRadius; // 水波的半径
    private int mIncrease; // 半径的增量
    private Handler mHandler = new Handler(Looper.myLooper()); // 声明一个处理器对象
    public RippleImageView(Context context) {
        this(context, null);
    }
    public RippleImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        mIncrease = Utils.dip2px(mContext, 5);
        mPaint.setColor(0x99ffffff); // 设置画笔颜色
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = getMeasuredWidth(); // 获取视图的实际宽度
        mHeight = getMeasuredHeight(); // 获取视图的实际高度
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mRadius > 0) {
            canvas.drawCircle(mWidth/2, mHeight/2, mRadius, mPaint); // 画水波
        }
    }
    // 设置水波的颜色
    public void setRippleColor(int color) {
        mPaint.setColor(color); // 设置画笔颜色
    }
    // 开始播放水波动画
    public void startRipple() {
        mRadius = 0;
        mHandler.post(mRipple); // 立即启动水波刷新任务
    }
    // 定义一个水波刷新任务
    private Runnable mRipple = new Runnable() {
        @Override
        public void run() {
            mRadius += mIncrease;
            if (mRadius*mRadius > (mWidth*mWidth/4 + mHeight*mHeight/4)) { // 水波半径已超出对角线
                mRadius = 0;
                mIncrease = Utils.dip2px(mContext, 5);
            } else { // 水波半径未超出对角线
                mIncrease += Utils.dip2px(mContext, 1);
                mHandler.postDelayed(this, 500); // 延迟50毫秒后再次启动水波刷新任务
            }
            postInvalidate(); // 立即刷新视图(线程安全方式)
        }
    };
}

XML文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:orientation="horizontal" >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:paddingLeft="5dp"
            android:gravity="center"
            android:text="水波特效样式:"
            android:textColor="@color/black"
            android:textSize="17sp" />
        <Spinner
            android:id="@+id/sp_ripple"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:spinnerMode="dialog" />
    </LinearLayout>
    <com.example.picture.widget.RippleImageView
        android:id="@+id/riv_scene"
        android:layout_width="match_parent"
        android:layout_height="270dp"
        android:src="@drawable/ylxs" />
</LinearLayout>

创作不易 觉得有帮助请 点赞关注收藏~~~

相关文章
|
3天前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
46 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
1天前
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
18 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
17天前
|
缓存 前端开发 Android开发
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
49 12
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
|
20天前
|
Dart 前端开发 Android开发
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
23 1
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
2月前
|
存储 监控 API
app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
70 11
|
2月前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
73 19
|
2月前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
83 14
|
2月前
|
开发框架 Android开发 iOS开发
安卓与iOS开发中的跨平台策略:一次编码,多平台部署
在移动应用开发的广阔天地中,安卓和iOS两大阵营各占一方。随着技术的发展,跨平台开发框架应运而生,它们承诺着“一次编码,到处运行”的便捷。本文将深入探讨跨平台开发的现状、挑战以及未来趋势,同时通过代码示例揭示跨平台工具的实际运用。
161 3
|
2月前
|
搜索推荐 前端开发 测试技术
打造个性化安卓应用:从设计到开发的全面指南
在这个数字时代,拥有一个定制的移动应用不仅是一种趋势,更是个人或企业品牌的重要延伸。本文将引导你通过一系列简单易懂的步骤,从构思你的应用理念开始,直至实现一个功能齐全的安卓应用。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你提供必要的工具和知识,帮助你将创意转化为现实。
APP开发的流程有哪些?
APP开发的过程当中,多多少少的也要遵循着自己的流程,从现有的一些情况来看,大多数的情况下再开发的过程当中加入着各种不同的开发方案,那么他们的流程究竟如何?
230 0

热门文章

最新文章

  • 1
    DeepSeek Artifacts:在线实时预览的前端 AI 编程工具,基于DeepSeek V3快速生成React App
  • 2
    【05】2025年1月首发完整版-篇幅较长-苹果app如何上架到app store完整流程·不借助第三方上架工具的情况下无需花钱但需仔细学习-优雅草央千澈详解关于APP签名以及分发-们最关心的一篇来了-IOS上架app
  • 3
    【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
  • 4
    【Azure Logic App】使用MySQL 新增行触发器遇见错误 :“Unknown column 'created_at' in 'order clause'”
  • 5
    【Azure Function】Function App出现System.IO.FileNotFoundException异常
  • 6
    电竞陪玩系统架构优化设计,陪玩app如何提升系统稳定性,陪玩小程序平台的测试与监控
  • 7
    【Azure App Service】对App Service中CPU指标数据中系统占用部分(System CPU)的解释
  • 8
    微信小程序 app.json 配置文件解析与应用
  • 9
    【01】vs-code如何配置flutter环境-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈-供大大的学习提升
  • 10
    轻松搭建婚恋交友系统源码,H5/小程序/APP自动适配,智能匹配恋爱交友平台快速落地