内容简介:原本我是想在BaseActivity的DecorView层添加一个View,奈何之前同事的Activity继承的五花八门。正好业务需要在因为要在手机上显示,所以必须用service来实现
原本我是想在BaseActivity的DecorView层添加一个View,奈何之前同事的Activity继承的五花八门。正好业务需要在 手机桌面 上显示一个可拖拽的FloatView。
使用到的权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
实现
因为要在手机上显示,所以必须用service来实现
public class CurrentNavigateFloatViewService extends Service {
private static final String TAG = "FloatViewService";
//定义浮动窗口布局
private LinearLayout mFloatLayout;
private WindowManager.LayoutParams wmParams;
//创建浮动窗口设置布局参数的对象
private WindowManager mWindowManager;
private ImageView mFloatView;
@Override
public void onCreate() {
super.onCreate();
createFloatView();
}
private int lastX;
private int dy;
@SuppressWarnings("static-access")
@SuppressLint("InflateParams")
private void createFloatView() {
wmParams = new WindowManager.LayoutParams();
//通过getApplication获取的是WindowManagerImpl.CompatModeWrapper
mWindowManager = (WindowManager) getApplication().getSystemService(getApplication().WINDOW_SERVICE);
int LAYOUT_FLAG;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
}
//设置window type
wmParams.type = LAYOUT_FLAG;
// wmParams.type = WindowManager.LayoutParams.TYPE_PHONE;
//设置图片格式,效果为背景透明
wmParams.format = PixelFormat.RGBA_8888;
//设置浮动窗口不可聚焦(实现操作除浮动窗口外的其他可见窗口的操作)
wmParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
//调整悬浮窗显示的停靠位置为左侧置顶
wmParams.gravity = Gravity.LEFT | Gravity.TOP;
// 以屏幕左上角为原点,设置x、y初始值,相对于gravity
wmParams.x = 0;
wmParams.y = 152;
//设置悬浮窗口长宽数据
wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
LayoutInflater inflater = LayoutInflater.from(getApplication());
//获取浮动窗口视图所在布局
mFloatLayout = (LinearLayout) inflater.inflate(R.layout.float_navigator, null);
//添加mFloatLayout
mWindowManager.addView(mFloatLayout, wmParams);
//浮动窗口按钮
mFloatView = (ImageView) mFloatLayout.findViewById(R.id.imgVew_float_view);
mFloatLayout.measure(View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED), View.MeasureSpec
.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
//设置监听浮动窗口的触摸移动
mFloatView.setOnTouchListener(new View.OnTouchListener() {
boolean isClick;
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
int dx = 0;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// mFloatView.setBackgroundResource(R.drawable.circle_red);
isClick = false;
lastX = (int) event.getRawX();
break;
case MotionEvent.ACTION_MOVE:
dx = (int) event.getRawX() - lastX;
isClick = true;
// getRawX是触摸位置相对于屏幕的坐标,getX是相对于按钮的坐标
wmParams.x = (int) event.getRawX()
- mFloatView.getMeasuredWidth() / 2;
// 减25为状态栏的高度
wmParams.y = (int) event.getRawY()
- mFloatView.getMeasuredHeight() / 2 - 75;
// 刷新
mWindowManager.updateViewLayout(mFloatLayout, wmParams);
return true;
case MotionEvent.ACTION_UP:
//靠边移动
int screenWidthHalf = ScreenUtil.getScreenWidth(CurrentNavigateFloatViewService.this) / 2;
int left = 0;
int right = ScreenUtil.getScreenWidth(CurrentNavigateFloatViewService.this) - mFloatLayout.getMeasuredWidth();
if (wmParams.x >= screenWidthHalf) {
wmParams.x = right;
mWindowManager.updateViewLayout(mFloatLayout, wmParams);
} else {
wmParams.x = left;
mWindowManager.updateViewLayout(mFloatLayout, wmParams);
}
return isClick;// 此处返回false则属于移动事件,返回true则释放事件,可以出发点击否。
default:
break;
}
return false;
}
});
mFloatView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(CurrentNavigateFloatViewService.this, "取消", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onDestroy() {
super.onDestroy();
if (mFloatLayout != null) {
//移除悬浮窗口
mWindowManager.removeView(mFloatLayout);
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
WindowPermissionCheck.java
public class WindowPermissionCheck {
public static boolean checkPermission(Activity activity){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& !Settings.canDrawOverlays(activity)) {
Toast.makeText(activity, "当前无权限,请授权", Toast.LENGTH_SHORT).show();
activity.startActivityForResult(
new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + activity.getPackageName())), 0);
return false;
}
return true;
}
public static void onActivityResult(Activity activity,
int requestCode,
int resultCode,
Intent data,
OnWindowPermissionListener onWindowPermissionListener) {
if (requestCode == 0) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& !Settings.canDrawOverlays(activity)) {
Toast.makeText(activity.getApplicationContext(), "授权失败", Toast.LENGTH_SHORT).show();
if(onWindowPermissionListener!=null)
onWindowPermissionListener.onFailure();
}else {
Toast.makeText(activity.getApplicationContext(), "授权成功", Toast.LENGTH_SHORT).show();
if(onWindowPermissionListener!=null)
onWindowPermissionListener.onSuccess();
}
}
}
public interface OnWindowPermissionListener{
void onSuccess();
void onFailure();
}
}
调用
因为要在手机上显示,即需要”在其他APP的上层“显示,在Android6.0以上,需要用户来”允许显示在其他应用的上层”
调用
if (WindowPermissionCheck.checkPermission(MainActivity.this)) {
Intent intent = new Intent(MainActivity.this, CurrentNavigateFloatViewService.class);
//启动FloatViewService
startService(intent);
}
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Writing Apache Modules with Perl and C
Lincoln Stein、Doug MacEachern / O'Reilly Media, Inc. / 1999-03 / USD 39.95
Apache is the most popular Web server on the Internet because it is free, reliable, and extensible. The availability of the source code and the modular design of Apache makes it possible to extend Web......一起来看看 《Writing Apache Modules with Perl and C》 这本书的介绍吧!