android 用java编写一个悬浮窗图片按钮,id为cat,点击cat 环绕展开 a b c 三个 image,自动吸附边缘时收回 a b c三个image ,并改变cat图片

时间: 2024-03-14 19:43:49 浏览: 21
好的,我可以为您提供一份示例代码。但是需要注意的是,悬浮窗功能需要使用android.permission.SYSTEM_ALERT_WINDOW权限,而且自动吸附边缘的实现需要使用WindowManager.LayoutParams的相关方法,这些方法可能不太容易理解,需要您具备一定的Android开发经验。 以下是示例代码: ```java public class FloatWindowActivity extends Activity { private WindowManager mWindowManager; private View mFloatView; private ImageView mCatView; private ImageView mAView; private ImageView mBView; private ImageView mCView; private boolean mExpanded = false; private boolean mMoving = false; private float mStartX, mStartY; private float mLastX, mLastY; private float mScreenWidth, mScreenHeight; private float mImageSize; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_float_window); mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE); mScreenWidth = mWindowManager.getDefaultDisplay().getWidth(); mScreenHeight = mWindowManager.getDefaultDisplay().getHeight(); mImageSize = getResources().getDimension(R.dimen.image_size); mFloatView = LayoutInflater.from(this).inflate(R.layout.view_float_window, null); mCatView = (ImageView) mFloatView.findViewById(R.id.cat); mAView = (ImageView) mFloatView.findViewById(R.id.a); mBView = (ImageView) mFloatView.findViewById(R.id.b); mCView = (ImageView) mFloatView.findViewById(R.id.c); mCatView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mExpanded) { collapse(); } else { expand(); } } }); mCatView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mMoving = false; mStartX = event.getRawX(); mStartY = event.getRawY(); mLastX = mStartX; mLastY = mStartY; break; case MotionEvent.ACTION_MOVE: float x = event.getRawX(); float y = event.getRawY(); float dx = x - mLastX; float dy = y - mLastY; if (Math.abs(dx) > 10 || Math.abs(dy) > 10) { mMoving = true; updatePosition(dx, dy); mLastX = x; mLastY = y; } break; case MotionEvent.ACTION_UP: if (!mMoving) { v.performClick(); } else { autoAttach(); } break; } return true; } }); WindowManager.LayoutParams params = new WindowManager.LayoutParams(); params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; params.format = PixelFormat.TRANSLUCENT; params.gravity = Gravity.TOP | Gravity.LEFT; params.width = WindowManager.LayoutParams.WRAP_CONTENT; params.height = WindowManager.LayoutParams.WRAP_CONTENT; params.x = 0; params.y = 0; mWindowManager.addView(mFloatView, params); } private void updatePosition(float dx, float dy) { WindowManager.LayoutParams params = (WindowManager.LayoutParams) mFloatView.getLayoutParams(); params.x += dx; params.y += dy; params.x = Math.max(0, Math.min((int) (mScreenWidth - mImageSize), params.x)); params.y = Math.max(0, Math.min((int) (mScreenHeight - mImageSize), params.y)); mWindowManager.updateViewLayout(mFloatView, params); } private void expand() { mExpanded = true; mCatView.setImageResource(R.drawable.cat2); mAView.setVisibility(View.VISIBLE); mBView.setVisibility(View.VISIBLE); mCView.setVisibility(View.VISIBLE); float degree = (float) (Math.PI / 4); float radius = mImageSize * 2; updatePosition(0, -radius); ObjectAnimator.ofFloat(mAView, "translationX", 0, radius * (float) Math.sin(degree)) .setDuration(300).start(); ObjectAnimator.ofFloat(mAView, "translationY", 0, -radius * (float) Math.cos(degree)) .setDuration(300).start(); ObjectAnimator.ofFloat(mBView, "translationX", 0, radius * (float) Math.cos(degree)) .setDuration(300).start(); ObjectAnimator.ofFloat(mBView, "translationY", 0, -radius * (float) Math.sin(degree)) .setDuration(300).start(); ObjectAnimator.ofFloat(mCView, "translationX", 0, radius) .setDuration(300).start(); } private void collapse() { mExpanded = false; mCatView.setImageResource(R.drawable.cat1); ObjectAnimator.ofFloat(mAView, "translationX", mAView.getTranslationX(), 0) .setDuration(300).start(); ObjectAnimator.ofFloat(mAView, "translationY", mAView.getTranslationY(), 0) .setDuration(300).start(); ObjectAnimator.ofFloat(mBView, "translationX", mBView.getTranslationX(), 0) .setDuration(300).start(); ObjectAnimator.ofFloat(mBView, "translationY", mBView.getTranslationY(), 0) .setDuration(300).start(); ObjectAnimator.ofFloat(mCView, "translationX", mCView.getTranslationX(), 0) .setDuration(300).start(); new Handler().postDelayed(new Runnable() { @Override public void run() { mAView.setVisibility(View.GONE); mBView.setVisibility(View.GONE); mCView.setVisibility(View.GONE); } }, 300); } private void autoAttach() { WindowManager.LayoutParams params = (WindowManager.LayoutParams) mFloatView.getLayoutParams(); int x = params.x; int y = params.y; int centerX = (int) (x + mImageSize / 2); int centerY = (int) (y + mImageSize / 2); int left = 0, top = 0, right = (int) mScreenWidth, bottom = (int) mScreenHeight; if (centerX < mScreenWidth / 2) { right = (int) (mScreenWidth / 2); } else { left = (int) (mScreenWidth / 2); } if (centerY < mScreenHeight / 2) { bottom = (int) (mScreenHeight / 2); } else { top = (int) (mScreenHeight / 2); } if (x < left) { ObjectAnimator.ofFloat(mFloatView, "translationX", x - left, 0) .setDuration(300).start(); params.x = left; } else if (x + mImageSize > right) { ObjectAnimator.ofFloat(mFloatView, "translationX", x + mImageSize - right, 0) .setDuration(300).start(); params.x = right - (int) mImageSize; } if (y < top) { ObjectAnimator.ofFloat(mFloatView, "translationY", y - top, 0) .setDuration(300).start(); params.y = top; } else if (y + mImageSize > bottom) { ObjectAnimator.ofFloat(mFloatView, "translationY", y + mImageSize - bottom, 0) .setDuration(300).start(); params.y = bottom - (int) mImageSize; } mWindowManager.updateViewLayout(mFloatView, params); } @Override protected void onDestroy() { super.onDestroy(); if (mFloatView != null) { mWindowManager.removeView(mFloatView); } } } ``` 布局文件view_float_window.xml如下: ```xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageView android:id="@+id/cat" android:layout_width="@dimen/image_size" android:layout_height="@dimen/image_size" android:src="@drawable/cat1"/> <ImageView android:id="@+id/a" android:layout_width="@dimen/image_size" android:layout_height="@dimen/image_size" android:src="@drawable/a" android:visibility="gone"/> <ImageView android:id="@+id/b" android:layout_width="@dimen/image_size" android:layout_height="@dimen/image_size" android:src="@drawable/b" android:visibility="gone"/> <ImageView android:id="@+id/c" android:layout_width="@dimen/image_size" android:layout_height="@dimen/image_size" android:src="@drawable/c" android:visibility="gone"/> </RelativeLayout> ``` 其中,@dimen/image_size定义了图片的大小,可以根据需要进行修改。同时,@drawable/cat1、@drawable/cat2、@drawable/a、@drawable/b、@drawable/c是五张图片资源,需要提前准备好放在res/drawable目录下。 希望这份代码对您有所帮助,若有疑问请随时提出。

相关推荐

最新推荐

recommend-type

Android悬浮窗按钮实现点击并显示/隐藏多功能列表

主要为大家详细介绍了Android悬浮窗按钮实现点击并显示/隐藏多功能列表,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
recommend-type

Android仿微信视屏悬浮窗效果

主要为大家详细介绍了Android仿微信视屏悬浮窗效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
recommend-type

Android自定义APP全局悬浮按钮

主要为大家详细介绍了Android自定义APP全局悬浮按钮,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
recommend-type

不依赖于Activity的Android全局悬浮窗的实现

在Android应用开发中,经常要遇到做全局悬浮窗的效果,本文的内容主要是如何不依赖于Activity的全局悬浮窗的实现及原理,有需要的可以参考。
recommend-type

Android自定义可拖拽的悬浮按钮DragFloatingActionButton

主要介绍了Android自定义可拖拽的悬浮按钮DragFloatingActionButton,需要的朋友可以参考下
recommend-type

zigbee-cluster-library-specification

最新的zigbee-cluster-library-specification说明文档。
recommend-type

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire
recommend-type

MATLAB柱状图在信号处理中的应用:可视化信号特征和频谱分析

![matlab画柱状图](https://img-blog.csdnimg.cn/3f32348f1c9c4481a6f5931993732f97.png) # 1. MATLAB柱状图概述** MATLAB柱状图是一种图形化工具,用于可视化数据中不同类别或组的分布情况。它通过绘制垂直条形来表示每个类别或组中的数据值。柱状图在信号处理中广泛用于可视化信号特征和进行频谱分析。 柱状图的优点在于其简单易懂,能够直观地展示数据分布。在信号处理中,柱状图可以帮助工程师识别信号中的模式、趋势和异常情况,从而为信号分析和处理提供有价值的见解。 # 2. 柱状图在信号处理中的应用 柱状图在信号处理
recommend-type

从键盘输入一段英文字符串,其中包含多个字母‘h',请编写程序利用正则表达式,将英文字符串中的’h'全部改为‘H’

好的,我可以帮您解决这个问题。 您可以使用 Python 编写一个程序来实现这个功能。具体步骤如下: 1. 首先导入 re 模块,这个模块是 Python 中用于处理正则表达式的模块。 2. 然后定义一个包含英文字符串的变量,例如: text = "This is a string containing multiple h's." 3. 接下来,使用 re.sub() 方法来进行替换操作。re.sub() 方法的第一个参数是正则表达式,第二个参数是替换的字符或字符串,第三个参数是被替换的字符串。在这个例子里,我们需要将所有的小写字母 h 替换成大写字母 H,所以正则表达式可以写成
recommend-type

JSBSim Reference Manual

JSBSim参考手册,其中包含JSBSim简介,JSBSim配置文件xml的编写语法,编程手册以及一些应用实例等。其中有部分内容还没有写完,估计有生之年很难看到完整版了,但是内容还是很有参考价值的。