Android 实现页面中自定义悬浮窗页面 磁吸四周工具类
时间: 2024-05-10 12:21:42 浏览: 130
以下是一个基于 Android 的自定义悬浮窗页面磁吸四周工具类的示例代码。
首先,我们需要定义一个 FloatingView 类,它继承自 FrameLayout,并实现了 View.OnTouchListener 接口。这个类表示悬浮窗页面,可以包含任意的子 View。
```
public class FloatingView extends FrameLayout implements View.OnTouchListener {
private int mLastX;
private int mLastY;
private int mStartX;
private int mStartY;
private int mScreenWidth;
private int mScreenHeight;
public FloatingView(Context context) {
this(context, null);
}
public FloatingView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public FloatingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
setOnTouchListener(this);
mScreenWidth = getResources().getDisplayMetrics().widthPixels;
mScreenHeight = getResources().getDisplayMetrics().heightPixels;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mStartX = (int) event.getRawX();
mStartY = (int) event.getRawY();
mLastX = mStartX;
mLastY = mStartY;
break;
case MotionEvent.ACTION_MOVE:
int dx = (int) (event.getRawX() - mLastX);
int dy = (int) (event.getRawY() - mLastY);
int x = getX() + dx;
int y = getY() + dy;
if (x < 0) {
x = 0;
}
if (x > mScreenWidth - getWidth()) {
x = mScreenWidth - getWidth();
}
if (y < 0) {
y = 0;
}
if (y > mScreenHeight - getHeight()) {
y = mScreenHeight - getHeight();
}
setX(x);
setY(y);
mLastX = (int) event.getRawX();
mLastY = (int) event.getRawY();
break;
case MotionEvent.ACTION_UP:
if (Math.abs(event.getRawX() - mStartX) < 5 && Math.abs(event.getRawY() - mStartY) < 5) {
performClick();
}
break;
}
return true;
}
}
```
接下来,我们编写一个辅助类,用于将悬浮窗页面磁吸到屏幕的四周。该类需要维护一个 FloatingView 对象,以及一些悬浮窗的位置信息。
```
public class FloatingViewHelper {
private static final int MARGIN = 10;
private FloatingView mFloatingView;
private int mScreenWidth;
private int mScreenHeight;
private int mLeft;
private int mTop;
private int mRight;
private int mBottom;
public FloatingViewHelper(Context context, FloatingView floatingView) {
mFloatingView = floatingView;
mScreenWidth = context.getResources().getDisplayMetrics().widthPixels;
mScreenHeight = context.getResources().getDisplayMetrics().heightPixels;
}
public void attachToWindow() {
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
params.format = PixelFormat.RGBA_8888;
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
params.gravity = Gravity.TOP | Gravity.LEFT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
mFloatingView.setLayoutParams(params);
mFloatingView.setOnTouchListener(mFloatingView);
WindowManager wm = (WindowManager) mFloatingView.getContext().getSystemService(Context.WINDOW_SERVICE);
wm.addView(mFloatingView, params);
}
public void detachFromWindow() {
WindowManager wm = (WindowManager) mFloatingView.getContext().getSystemService(Context.WINDOW_SERVICE);
wm.removeView(mFloatingView);
}
public void snapToEdge() {
int centerX = (mLeft + mRight) / 2;
int centerY = (mTop + mBottom) / 2;
if (centerX < mScreenWidth / 2) {
mFloatingView.setX(0 + MARGIN);
mLeft = 0;
mRight = mLeft + mFloatingView.getWidth();
} else {
mFloatingView.setX(mScreenWidth - mFloatingView.getWidth() - MARGIN);
mRight = mScreenWidth;
mLeft = mRight - mFloatingView.getWidth();
}
if (centerY < mScreenHeight / 2) {
mFloatingView.setY(0 + MARGIN);
mTop = 0;
mBottom = mTop + mFloatingView.getHeight();
} else {
mFloatingView.setY(mScreenHeight - mFloatingView.getHeight() - MARGIN);
mBottom = mScreenHeight;
mTop = mBottom - mFloatingView.getHeight();
}
}
public void updatePosition() {
mLeft = (int) mFloatingView.getX();
mTop = (int) mFloatingView.getY();
mRight = mLeft + mFloatingView.getWidth();
mBottom = mTop + mFloatingView.getHeight();
}
}
```
最后,我们可以在 Activity 中使用这个辅助类来实现悬浮窗的磁吸效果。
```
public class MainActivity extends AppCompatActivity {
private FloatingView mFloatingView;
private FloatingViewHelper mFloatingViewHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFloatingView = new FloatingView(this);
mFloatingView.setBackgroundColor(Color.YELLOW);
mFloatingViewHelper = new FloatingViewHelper(this, mFloatingView);
mFloatingViewHelper.attachToWindow();
}
@Override
protected void onDestroy() {
super.onDestroy();
mFloatingViewHelper.detachFromWindow();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
mFloatingViewHelper.snapToEdge();
mFloatingViewHelper.updatePosition();
}
}
}
```
这里,我们在 onCreate 方法中创建了一个 FloatingView 对象,并将其添加到 Activity 的界面中。然后,我们创建了一个 FloatingViewHelper 对象,将其附加到 FloatingView 上,并将其添加到 WindowManager 中显示。在 onDestroy 方法中,我们从 WindowManager 中移除了 FloatingView。
在 onWindowFocusChanged 方法中,我们在 Activity 获取焦点时调用了 snapToEdge 方法,将 FloatingView 磁吸到屏幕的四周。我们还调用了 updatePosition 方法,更新了悬浮窗的位置信息。这样,我们就实现了一个简单的悬浮窗页面磁吸四周工具类。
阅读全文