android 用java编写一个悬浮窗图片按钮,id为cat,点击cat 环绕展开 a b c 三个 image,自动吸附边缘时收回 a b c三个image ,并改变cat图片
时间: 2024-03-14 09:43:49 浏览: 67
Android实现悬浮图片
好的,我可以为您提供一份示例代码。但是需要注意的是,悬浮窗功能需要使用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目录下。
希望这份代码对您有所帮助,若有疑问请随时提出。
阅读全文