android java 用系统弹窗的方式实现模拟点击动画特效

接上一篇:android java系统弹窗的基础模板-CSDN博客

本篇记录的是系统弹窗的一个应用示例:实现点击动画效果

首先模拟点击的实现参考:android模拟点击_motionevent upevent = motionevent.obtain(systemclo-CSDN博客

动画效果,是指点击之后,在点击的中心坐标,播放一个固定时长的动画。

因为需要能够在其他应用上播放动画,所以可以使用系统悬浮窗,即系统弹窗来实现。

实现上很多可参考android java系统弹窗的基础模板-CSDN博客

1、资源文件xml比模板更简单

app\src\main\res\layout\click_layout.xml

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="match_parent"
	android:layout_height="match_parent">
	<ImageView
		android:id="@+id/clickImageView"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"/>
</LinearLayout>

因为只需要一个view,不需要其他ui控件,所以更简单

2、代码实现

2.1 初始化同模板

特意初始化了一下动画image的高度

rootView初始化,AddOrUpdateView我封装的用来添加rootView到windowManager的接口。rootView初始设置为隐藏。

java 复制代码
    private View rootView;
    private ImageView imageView;
    private Context farContext;
    private int imageHeight;    

    public void Init(Context context) {
        farContext = context;
        rootView = LayoutInflater.from(context).inflate(R.layout.click_layout, null);
        imageView = rootView.findViewById(R.id.clickImageView);

        imageHeight = ScreenResolutionReceiver.getResolutionHeight() / 20;

        AddOrUpdateView(rootView, 0, 0, true);
        rootView.setVisibility(View.GONE);
    }

2.2 AddOrUpdateView封装,方便复用

WindowManager.LayoutParams params设置悬浮窗的高度宽度为资源文件的初始高度宽度,且为叠加在上方形式overlay,背景为透明色(因为会加载动画,所以不需要背景色)。

用入参x、y动态调整悬浮窗的位置。 - imageHeight / 2保证悬浮窗的中心点是鼠标点击的坐标点。

java 复制代码
    private WindowManager windowManager;

    private void AddOrUpdateView(View view, int x, int y, boolean add) {
        windowManager = (WindowManager)farContext.getSystemService(WINDOW_SERVICE);

        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT, // 初始高度
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSPARENT);

        params.gravity = Gravity.LEFT | Gravity.TOP;
        params.x = x - imageHeight / 2;
        params.y = y - imageHeight / 2;

        if (add) {
            windowManager.addView(view, params);
        } else {
            windowManager.updateViewLayout(view, params);
        }
    }

2.3 加载gif动画,实现点击特效

使用了Glide来加载gif,glide组件,本身是需要在build.gradle的dependencies里添加下面两行:

java 复制代码
    implementation 'com.github.bumptech.glide:glide:4.12.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'

点击则触发播放1s的动画效果,要实现的逻辑如下:

弹窗设置为显示的同时,加载gif,执行一次动画效果就够了,然后设定为1s(经验值)后隐藏弹窗。

主要是超时这块比较难搞,尝试了几种写法都不好用。不断调整搜索的关键字,最终找到了handler msg.what的用法。

这块值得一说的是,使用AIGC来做件事的效率,不如使用搜索引擎。因为android开发的特点,就是方法过多过杂,不少方法都是过时、不完整的、甚至错误的。这也是和android本身历史版本过多有关,且有些网上文章给出的就是针对某些特殊硬件的。所以,这种情况下,AI大模型本身的训练数据可能就有些脏,往往也给不出好的方案。而且大模型的回答过于正规,增加了阅读、试错的时间成本呢。对于已经能够熟练使用搜索引擎的人来说,使用后者的效率高得多。

如下,在glide的listener(new RequestListener<GifDrawable>()里,先设置循环次数为1,再模拟发送一个空的延时消息。然后在handler的处理队列里,设置弹窗为隐藏。

java 复制代码
    private final int delaytime = 1000;
    private final int msgWhat = 1;  // 随便设置都可以

    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == msgWhat) {
                rootView.setVisibility(View.GONE);
            }
        }
    };

    public void LoadGif(int x, int y) {
        AddOrUpdateView(rootView, x, y, false);

        rootView.setVisibility(View.VISIBLE);

        int resourceId = R.drawable.click_loading;
        new Handler(Looper.getMainLooper()).post(() -> {
                    Glide.with(getContext())
                            .asGif()
                            .load(resourceId)
                            .override(imageHeight, imageHeight) // 保持宽高比,限制高度
                            .diskCacheStrategy(DiskCacheStrategy.ALL)
                            .listener(new RequestListener<GifDrawable>() {
                                @Override
                                public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<GifDrawable> target, boolean isFirstResource) {
                                    return false;
                                }

                                @Override
                                public boolean onResourceReady(GifDrawable resource, Object model, Target<GifDrawable> target, DataSource dataSource, boolean isFirstResource) {
                                    resource.setLoopCount(1); // 设置循环次数为1

                                    //发送延时消息,通知动画结束
                                    //以下两个参数都是 int 型,记得如上的声明
                                    handler.sendEmptyMessageDelayed(msgWhat, delaytime);
                                    return false;
                                }
                            })
                            .into(imageView);
                }
        );
    }
相关推荐
tangweiguo0305198711 分钟前
Flutter与原生混合开发:实现完美的暗夜模式同步方案
android·flutter
雨白1 小时前
深入理解 Android 触摸事件:以实现 ViewPager 为例
android
shenshizhong1 小时前
看懂鸿蒙系统源码 比较重要的知识点
android·harmonyos
一只修仙的猿3 小时前
再谈性能优化,一次项目优化经历分享
android·性能优化
雮尘5 小时前
Android性能优化之枚举替代
android
2501_915909067 小时前
苹果上架App软件全流程指南:iOS 应用发布步骤、App Store 上架流程、uni-app 打包上传与审核技巧详解
android·ios·小程序·https·uni-app·iphone·webview
2501_915921437 小时前
iOS 文件管理与能耗调试结合实战 如何查看缓存文件、优化电池消耗、分析App使用记录(uni-app开发与性能优化必备指南)
android·ios·缓存·小程序·uni-app·iphone·webview
2501_915918417 小时前
App 苹果 上架全流程解析 iOS 应用发布步骤、App Store 上架流程
android·ios·小程序·https·uni-app·iphone·webview
2501_916007478 小时前
苹果上架全流程详解,iOS 应用发布步骤、App Store 上架流程、uni-app 打包上传与审核要点完整指南
android·ios·小程序·https·uni-app·iphone·webview
PuddingSama9 小时前
Android 高级绘制技巧: BlendMode
android·前端·面试