效果如上图所示
安卓小白记录学习过程。一起交流学习。有问题请多多指出。话不多说进入正题。
一、思路
首先明确需求,我们需要做一个右划弹出一个快捷切换应用的弹窗。
悬浮窗可以在其他应用上层显示出来,那么我们可以设置一个透明的悬浮窗让它显示在其他应用上层,然后通过这个悬浮窗只需要写一个滑动的监听事件。满足条件去弹出一个PopupWindow即可。那么有了思路按部就班去实现就OK了。
二、实现
(1)第一步实现一个显示在其他应用上层的悬浮窗
主布局简单写个按钮去弹出悬浮窗就行,这个看情况而定。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/button_star_service"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="启动悬浮窗"/>
</LinearLayout>
我们需要右划去弹出PopupWindow那么我们可以写一个透明的控件放在右边缘,我用的是一个宽10dp和和手机屏幕等高的一个TextView,用什么都可以只要看不到即可。
float_window.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<TextView
android:id="@+id/textview_float_window"
android:layout_width="10dp"
android:layout_height="match_parent"/>
</LinearLayout>
MainActivity简单写个Button点击事件去启动悬浮窗就行了
MainActivity.java
package com.example.floatingwindow;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button_star_service);
button.setOnClickListener(this::onClick);
}
@Override
public void onClick(View view) {
/**
* 启动悬浮窗并且获取悬浮窗权限
*/
FloatWindowManager floatWindowManager = new FloatWindowManager();
floatWindowManager.requestPermission(this);
floatWindowManager.initManager(this);
floatWindowManager.showFloatWindow();
}
}
FloatWindowManager用于创建悬浮窗,和设置悬浮窗的滑动事件
FloatWindowManager.java
package com.example.floatingwindow;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.PixelFormat;
import android.os.Build;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
public class FloatWindowManager {
private volatile static FloatWindowManager mInstance;
private WindowManager mWindowManager;
private Context mContext;
private WindowManager.LayoutParams mLayoutParams;
private int layoutY;
private int layoutX;
private View view;
public static synchronized FloatWindowManager getInstance() {
if (mInstance == null) {
synchronized (FloatWindowManager.class) {
if (mInstance == null) {
mInstance = new FloatWindowManager();
}
}
}
return mInstance;
}
/**
* 创建悬浮窗
* @param context
* @return
*/
public FloatWindowManager initManager(Context context) {
mContext = context;
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
showWindow();
return this;
}
/**
* 是否有悬浮框权限
*
* @return
*/
public boolean requestPermission(Context context) {
return SettingsCompat.canDrawOverlays(context, true, false);
}
/**
* 加载 悬浮窗 没有内容
*/
private synchronized void showWindow() {
view = LayoutInflater.from(mContext).inflate(R.layout.float_window,null);
mLayoutParams = new WindowManager.LayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
mLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
}
mLayoutParams.format = PixelFormat.RGBA_8888; //窗口透明
mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP; //窗口位置
mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
layoutY = 0;
layoutX = displayMetrics.widthPixels;
mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
mLayoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
mLayoutParams.x = layoutX;
mLayoutParams.y = layoutY;
setListener();
}
/**
* 显示悬浮窗
*/
public void showFloatWindow(){
mWindowManager.addView(view,mLayoutParams);
}
/**
* 设置 悬浮窗 view 滑动事件
*/
private void setListener() {
if (view != null) {
view.setOnTouchListener(new View.OnTouchListener() {
private int moveX; //平移距离
int startX, startY,endX,endY; //起始点
boolean isMove; //是否在移动
long startTime;//划动时间
boolean downMove = false;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = (int) event.getX();
startY = (int) event.getY();
startTime = System.currentTimeMillis();
isMove = false;
downMove = false;
return false;
case MotionEvent.ACTION_MOVE:
return true;
case MotionEvent.ACTION_UP:
long curTime = System.currentTimeMillis();
endX = (int) event.getX();
endY = (int) event.getY();
isMove = curTime - startTime > 100;
if (is