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>

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

相关文章
|
9月前
|
Android开发 数据安全/隐私保护 开发者
Android自定义view之模仿登录界面文本输入框(华为云APP)
本文介绍了一款自定义输入框的实现,包含静态效果、hint值浮动动画及功能扩展。通过组合多个控件完成界面布局,使用TranslateAnimation与AlphaAnimation实现hint文字上下浮动效果,支持密码加密解密显示、去除键盘回车空格输入、光标定位等功能。代码基于Android平台,提供完整源码与attrs配置,方便复用与定制。希望对开发者有所帮助。
172 0
|
5月前
|
存储 小程序 Java
热门小程序源码合集:微信抖音小程序源码支持PHP/Java/uni-app完整项目实践指南
小程序已成为企业获客与开发者创业的重要载体。本文详解PHP、Java、uni-app三大技术栈在电商、工具、服务类小程序中的源码应用,提供从开发到部署的全流程指南,并分享选型避坑与商业化落地策略,助力开发者高效构建稳定可扩展项目。
|
6月前
|
存储 Java PHP
轻量化短视频电商直播带货APP源码全解析:核心功能与设计流程​
在电商直播热潮下,开发专属直播带货APP成为抢占市场关键。本文详解原生开发轻量化APP的核心功能与全流程设计,涵盖用户登录、商品浏览、直播互动、购物车、订单及售后功能,并介绍安卓端Java、苹果端Object-C、后台PHP的技术实现,助力打造高效优质的直播电商平台。
|
7月前
|
存储 Android开发 数据安全/隐私保护
Thanox安卓系统增加工具下载,管理、阻止、限制后台每个APP运行情况
Thanox是一款Android系统管理工具,专注于权限、后台启动及运行管理。支持应用冻结、系统优化、UI自定义和模块管理,基于Xposed框架开发,安全可靠且开源免费,兼容Android 6.0及以上版本。
812 4
|
8月前
|
消息中间件 缓存 小程序
婚恋交友相亲公众号app小程序系统源码「脱单神器」婚恋平台全套代码 - 支持快速二次开发
这是一套基于SpringBoot + Vue3开发的婚恋交友系统,支持微信公众号、Uniapp小程序和APP端。系统包含实名认证、智能匹配、视频相亲、会员体系等功能,适用于婚恋社交平台和相亲交友应用。后端采用SpringBoot 3.x与MyBatis-Plus,前端使用Vue3与Uniapp,支持快速部署和二次开发。适合技术团队或有经验的个人创业者使用。
562 8
|
7月前
|
小程序 Java 关系型数据库
圈子系统公众号app小程序系统源码圈子系统带即时通讯 多级圈子系统源码 兴趣小组系统开源 私密圈子系统代码 会员制社区系统
本圈子系统解决方案提供即时通讯、多级圈子、兴趣小组、私密社区及会员制管理功能。支持开源与商业方案,推荐ThinkSNS+、EasyClub及OpenFire等系统,并提供前后端技术选型建议,助力快速搭建社交平台。
410 0
|
10月前
|
数据采集 JSON 网络安全
移动端数据抓取:Android App的TLS流量解密方案
本文介绍了一种通过TLS流量解密技术抓取知乎App热榜数据的方法。利用Charles Proxy解密HTTPS流量,分析App与服务器通信内容;结合Python Requests库模拟请求,配置特定请求头以绕过反爬机制。同时使用代理IP隐藏真实IP地址,确保抓取稳定。最终成功提取热榜标题、内容简介、链接等信息,为分析热点话题和用户趋势提供数据支持。此方法也可应用于其他Android App的数据采集,但需注意选择可靠的代理服务。
427 11
移动端数据抓取:Android App的TLS流量解密方案
不封号的外卖抢单神器,美团抢单辅助器app,autojs版本源码
这个代码提供了基础框架,包含主循环、订单检测和点击功能。实际使用时需要根据美团骑手AP
|
存储 缓存 安全
Android14 适配之——现有 App 安装到 Android14 手机上需要注意些什么?
Android14 适配之——现有 App 安装到 Android14 手机上需要注意些什么?
1012 0