悬浮窗
一、原理
1、添加独立的View
我们在APP中想不依赖Activity中的布局添加View时,可以通过WindowManager.addView()的方式,创建一个window,并显示添加的View。
2、Window可分为三类
应用window:一般位于最底层,对应一个Activity;
子window:不能单独存在,需要附属在父window上,如Dialog;
系统window:一般位于最顶层,不会被其他window遮住,如Toast。
二、悬浮窗
1、检查权限
// 检查悬浮窗
Settings.canDrawOverlays(mContext)
// 跳转到悬浮窗设置页面
activity.startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + activity.getPackageName())), requestCode);
2、添加悬浮窗
此处需要注意的是flag对于悬浮窗的影响:
FLAG_NOT_TOUCH_MODAL: 悬浮窗外部可响应事件
FLAG_NOT_FOCUSABLE : 不处理系统按钮事件
FLAG_LAYOUT_NO_LIMITS: 悬浮窗可以延伸到屏幕外
if (Settings.canDrawOverlays(mContext)) {
// 获取WindowManager服务
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
mLayoutParams = new WindowManager.LayoutParams();
// 设置LayoutParam
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
mLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
}
// 悬浮窗外部可响应事件
mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// 不处理系统按钮事件
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
// 悬浮窗可以延伸到屏幕外
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
mLayoutParams.format = PixelFormat.RGBA_8888;
mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
mLayoutParams.gravity = Gravity.TOP | Gravity.START;
mLayoutParams.x = 0;
mLayoutParams.y = 300;
// 将悬浮窗控件添加到WindowManager
mWindowManager.addView(mRootView, mLayoutParams);
}
// 移除悬浮窗
try {
mWindowManager.removeView(mRootView);
} catch (Exception e) {
//nothing
}
3、响应点击事件
// 可以给view直接设置
mRootView.setOnClickListener(onClickListener);
4、拖动
首先, 在ACTION_DOWN中记录当前的x,y位置;
然后, 在ACTION_MOVE中判断滑动距离,如果触发了滑动,算出滑动后的x,y位置,通过updateViewLayout进行更新;
最后, 在ACTION_UP中处理贴边,点击等逻辑。
// 拖动可以给view设置时间监听
if (canDrag) {
mRootView.setOnTouchListener(new EFWindowOnTouchListener());
}
private class EFWindowOnTouchListener implements View.OnTouchListener {
private boolean isMoved;
private int oX;
private int oY;
private int x;
private int y;
@Override
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 初始化滑动的标记
isMoved = false;
oX = (int) event.getRawX();
oY = (int) event.getRawY();
x = (int) event.getRawX();
y = (int) event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
int nowX = (int) event.getRawX();
int nowY = (int) event.getRawY();
int movedX = nowX - x;
int movedY = nowY - y;
x = nowX;
y = nowY;
// 如果没有触发滑动,则进行滑动判断
if (!isMoved && (Math.abs(oX - x) > mMinScrollDistance || Math.abs(oY - y) > mMinScrollDistance)) {
isMoved = true;
}
// 拖动中不能用贴边计算
mLayoutParams.x = getRealX(mLayoutParams.x + movedX, false, false);
mLayoutParams.y = getRealY(mLayoutParams.y + movedY, false);
mWindowManager.updateViewLayout(view, mLayoutParams);
break;
case MotionEvent.ACTION_UP:
if (mIsSticky) {
int viewWidth = view.getMeasuredWidth();
int screenWidth = ScreenUtils.getScreenWidth(mContext);
// 贴边终点只有左、右两种状态
if ((mLayoutParams.x + viewWidth / 2) > screenWidth / 2) {
if (mOnPositionListener != null) {
mOnPositionListener.onPositionChanged(OnPositionListener.POSITION_RIGHT);
}
mLayoutParams.x = screenWidth - viewWidth - mXEdgeSize;
} else {
if (mOnPositionListener != null) {
mOnPositionListener.onPositionChanged(OnPositionListener.POSITION_LEFT);
}
mLayoutParams.x = mXEdgeSize;
}
mWindowManager.updateViewLayout(view, mLayoutParams);
}
// 处理移动后还会响应点击事件的情况
if (isMoved) {
isMoved = false;
return true;
}
break;
default:
break;
}
return false;
}
}
5、横竖屏切换适配
监听到屏幕变化后,由于屏幕的长宽发生了变化,重新计算当前的x,y,并进行更新。
// 添加屏幕变化监听
DisplayManager displayManager = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
displayManager.registerDisplayListener(new DisplayManager.DisplayListener() {
@Override
public void onDisplayAdded(int displayId) {
}
@Override
public void onDisplayRemoved(int displayId) {
}
@Override
public void onDisplayChanged(int displayId) {
// 监听到屏幕发生变化
if (mLayoutParams != null && mWindowManager != null
&& mRootView != null && mRootView.isAttachedToWindow()) {
mLayoutParams.x = getRealX(mLayoutParams.x, false, true);
mLayoutParams.y = getRealY(mLayoutParams.y, false);
mWindowManager.updateViewLayout(mRootView, mLayoutParams);
}
}
}, new Handler(Looper.getMainLooper()));
6、贴边,缩进等处理
private int getRealX(int xPosition, boolean isInit, boolean considerSticky) {
if (isInit) {
// 此时view还没有触发测量,主动测量一次
getRootView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
}
int viewWidth = getRootView().getMeasuredWidth();
int screenWidth = ScreenUtils.getScreenWidth(mContext);
int screenHeight = ScreenUtils.getScreenHeight(mContext);
// 部分手机,如:vivo R9s,横竖屏切换,获取的值不会发生变化,此处做一个适配
screenWidth = isHorizontalScreen(mContext) ? Math.max(screenWidth, screenHeight) : Math.min(screenWidth, screenHeight);
// 贴边初始只有左和右,没有中间态
if (considerSticky && mIsSticky) {
if ((xPosition + viewWidth / 2) > screenWidth / 2) {// 处理缩进
if (mOnPositionListener != null) {
mOnPositionListener.onPositionChanged(OnPositionListener.POSITION_RIGHT);
}
// 贴右边显示,真实坐标为(屏幕宽度 - view的宽度 - x边距)
return screenWidth - viewWidth - mXEdgeSize;
} else {
if (mOnPositionListener != null) {
mOnPositionListener.onPositionChanged(OnPositionListener.POSITION_LEFT);
}
// 贴左边显示,真实坐标为(左起点 + x边距),左边的起点为0。
return mXEdgeSize;
}
} else {
if (xPosition > (screenWidth - viewWidth - mXEdgeSize)) {
if (mOnPositionListener != null) {
mOnPositionListener.onPositionChanged(OnPositionListener.POSITION_RIGHT);
}
// 当前位置已经超过允许的右边距,返回最右边距
return screenWidth - viewWidth - mXEdgeSize;
} else if (xPosition < mXEdgeSize) {
if (mOnPositionListener != null) {
mOnPositionListener.onPositionChanged(OnPositionListener.POSITION_LEFT);
}
// 当前位置小于允许的左边距,返回最左边距
return mXEdgeSize;
} else {
if (mOnPositionListener != null) {
mOnPositionListener.onPositionChanged(OnPositionListener.POSITION_MIDDLE);
}
// 由于不吸边,所以展示真实位置
return xPosition;
}
}
}
private int getRealY(int yPosition, boolean isInit) {
// 此时view还没有触发测量,主动测量一次
if (isInit) {
getRootView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
}
int viewHeight = getRootView().getMeasuredHeight();
int screenWidth = ScreenUtils.getScreenWidth(mContext);
int screenHeight = ScreenUtils.getScreenHeight(mContext);
// 部分手机,如:vivo R9s,横竖屏切换,获取的值不会发生变化,此处做一个适配
screenHeight = isHorizontalScreen(mContext) ? Math.min(screenWidth, screenHeight) : Math.max(screenWidth, screenHeight);
if (yPosition > (screenHeight - viewHeight - mYBottomEdgeSize)) {
// 当前位置已经超过允许的下边距,返回最下边距
return screenHeight - viewHeight - mYBottomEdgeSize;
} else if (yPosition < mYTopEdgeSize) {
// 当前位置小于允许的上边距,返回最上边距
return mYTopEdgeSize;
} else {
// 展示真实位置
return yPosition;
}
}
private boolean isHorizontalScreen(Context context) {
int angle = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
//屏幕旋转90°或270°,表示横屏
return angle == Surface.ROTATION_90 || angle == Surface.ROTATION_270;
}
三、注意
部分场景需要点击回到当前的Activity,可以参考如下代码:
// 方法一:跳转到app展示的上一个页面
public void onClick(View v) {
Intent intent = BaseApplication.getGlobalContext().getPackageManager().getLaunchIntentForPackage(BaseApplication.getGlobalContext().getPackageName());
BaseApplication.getGlobalContext().startActivity(intent);
}
// 方法二:本地缓存页面,判断登录状态跳转不同的页面
public void onClick(View v) {
// 注意,这里的跳转没有参数传递,在一些activity的onNewIntent中会对intent进行再次解析
// 因此,需要判断是否是从悬浮窗跳过去的,进行拦截,防止出现异常
// 也可以将正确的参数传递过去,成本较高,用作备选项
// FLAG_ACTIVITY_SINGLE_TOP,如果当前activity已经在栈顶,不再创建,直接跳转
// FLAG_ACTIVITY_REORDER_TO_FRONT,如果activity已经创建了,如:ABCD,跳转到B,不会重新创建,且变为ACDB
if (ACCOUNT_CONTROLLER.hasLogin()) {
if (mCurrentActivity != null) {
// 正常情况都不是null,除非长时间被系统回收了
Intent targetIntent = new Intent(BaseApplication.getGlobalContext(), mCurrentActivity.getClass());
targetIntent.putExtra(SpName.INTENT_FROM, FROM_EFWINDOW);
targetIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
mCurrentActivity.startActivity(targetIntent);
} else {
// 跳转首页,然后通过恢复接口进行再次跳转
Intent targetIntent = new Intent(BaseApplication.getGlobalContext(), HomeActivity.class);
targetIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
targetIntent.putExtra(SpName.INTENT_FROM, FROM_EFWINDOW);
BaseApplication.getGlobalContext().startActivity(targetIntent);
}
} else {
// 登录信息失效了
Intent targetIntent = new Intent(BaseApplication.getGlobalContext(), LoginActivity.class);
targetIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
targetIntent.putExtra(SpName.INTENT_FROM, FROM_EFWINDOW);
BaseApplication.getGlobalContext().startActivity(targetIntent);
ToastUtil.showMessage("登录信息失效,请重新登录");
}
}
四、悬浮窗代码
//try {
// if (mEfWindow == null) {
// View view = LayoutInflater.from(BaseApplication.getGlobalContext()).inflate(R.layout.layout_edj_floating_window, null);
// mEfWindow = new EFWindow.Builder(BaseApplication.getGlobalContext())
// .view(view)
// .yPosition(ScreenUtils.getScreenHeight(BaseApplication.getGlobalContext()) / 3)
// .isSticky(true)
// .canDrag(true)
// .xEdgeSize(-UIUtils.dp2px(BaseApplication.getGlobalContext(), 20))
// .onClickListener(this)
// .build();
// }
// mEfWindow.show();
//} catch (Exception e) {
// e.printStackTrace();
//}
public class EFWindow {
private final int mMinScrollDistance;
private WindowManager mWindowManager;
private WindowManager.LayoutParams mLayoutParams;
private final View mRootView;
private boolean mIsShow;
private boolean mIsSticky;
private int mXEdgeSize;
private int mYTopEdgeSize;
private int mYBottomEdgeSize;
private OnPositionListener mOnPositionListener;
private final Context mContext;
@RequiresApi(api = Build.VERSION_CODES.M)
private EFWindow(Builder builder) {
// 赋值
mContext = builder.mContext;
mMinScrollDistance = ViewConfiguration.get(mContext).getScaledTouchSlop();
mIsSticky = builder.mIsSticky;
mXEdgeSize = builder.mXEdgeSize;
mYTopEdgeSize = builder.mYTopEdgeSize;
mYBottomEdgeSize = builder.mYBottomEdgeSize;
mOnPositionListener = builder.mOnPositionListener;
mRootView = builder.mRootView;
boolean canDrag = builder.mCanDrag;
int xPosition = builder.mXPosition;
int yPosition = builder.mYPosition;
View.OnClickListener onClickListener = builder.mOnClickListener;
// 添加屏幕变化监听
DisplayManager displayManager = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
displayManager.registerDisplayListener(new DisplayManager.DisplayListener() {
@Override
public void onDisplayAdded(int displayId) {
}
@Override
public void onDisplayRemoved(int displayId) {
}
@Override
public void onDisplayChanged(int displayId) {
// 监听到屏幕发生变化
if (mLayoutParams != null && mWindowManager != null
&& mRootView != null && mRootView.isAttachedToWindow()) {
mLayoutParams.x = getRealX(mLayoutParams.x, false, true);
mLayoutParams.y = getRealY(mLayoutParams.y, false);
mWindowManager.updateViewLayout(mRootView, mLayoutParams);
}
}
}, new Handler(Looper.getMainLooper()));
if (Settings.canDrawOverlays(mContext)) {
// 获取WindowManager服务
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
if (canDrag) {
mRootView.setOnTouchListener(new EFWindowOnTouchListener());
}
mRootView.setOnClickListener(onClickListener);
mLayoutParams = new WindowManager.LayoutParams();
// 设置LayoutParam
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
mLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
}
// 悬浮窗外部可响应事件
mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// 不处理系统按钮事件
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
// 悬浮窗可以延伸到屏幕外
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
mLayoutParams.format = PixelFormat.RGBA_8888;
mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
mLayoutParams.gravity = Gravity.TOP | Gravity.START;
mLayoutParams.x = getRealX(xPosition, true, true);
mLayoutParams.y = getRealY(yPosition, true);
}
}
private int getRealX(int xPosition, boolean isInit, boolean considerSticky) {
if (isInit) {
// 此时view还没有触发测量,主动测量一次
getRootView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
}
int viewWidth = getRootView().getMeasuredWidth();
int screenWidth = ScreenUtils.getScreenWidth(mContext);
int screenHeight = ScreenUtils.getScreenHeight(mContext);
// 部分手机,如:vivo R9s,横竖屏切换,获取的值不会发生变化,此处做一个适配
screenWidth = isHorizontalScreen(mContext) ? Math.max(screenWidth, screenHeight) : Math.min(screenWidth, screenHeight);
// 贴边初始只有左和右,没有中间态
if (considerSticky && mIsSticky) {
if ((xPosition + viewWidth / 2) > screenWidth / 2) {// 处理缩进
if (mOnPositionListener != null) {
mOnPositionListener.onPositionChanged(OnPositionListener.POSITION_RIGHT);
}
// 贴右边显示,真实坐标为(屏幕宽度 - view的宽度 - x边距)
return screenWidth - viewWidth - mXEdgeSize;
} else {
if (mOnPositionListener != null) {
mOnPositionListener.onPositionChanged(OnPositionListener.POSITION_LEFT);
}
// 贴左边显示,真实坐标为(左起点 + x边距),左边的起点为0。
return mXEdgeSize;
}
} else {
if (xPosition > (screenWidth - viewWidth - mXEdgeSize)) {
if (mOnPositionListener != null) {
mOnPositionListener.onPositionChanged(OnPositionListener.POSITION_RIGHT);
}
// 当前位置已经超过允许的右边距,返回最右边距
return screenWidth - viewWidth - mXEdgeSize;
} else if (xPosition < mXEdgeSize) {
if (mOnPositionListener != null) {
mOnPositionListener.onPositionChanged(OnPositionListener.POSITION_LEFT);
}
// 当前位置小于允许的左边距,返回最左边距
return mXEdgeSize;
} else {
if (mOnPositionListener != null) {
mOnPositionListener.onPositionChanged(OnPositionListener.POSITION_MIDDLE);
}
// 由于不吸边,所以展示真实位置
return xPosition;
}
}
}
private int getRealY(int yPosition, boolean isInit) {
// 此时view还没有触发测量,主动测量一次
if (isInit) {
getRootView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
}
int viewHeight = getRootView().getMeasuredHeight();
int screenWidth = ScreenUtils.getScreenWidth(mContext);
int screenHeight = ScreenUtils.getScreenHeight(mContext);
// 部分手机,如:vivo R9s,横竖屏切换,获取的值不会发生变化,此处做一个适配
screenHeight = isHorizontalScreen(mContext) ? Math.min(screenWidth, screenHeight) : Math.max(screenWidth, screenHeight);
if (yPosition > (screenHeight - viewHeight - mYBottomEdgeSize)) {
// 当前位置已经超过允许的下边距,返回最下边距
return screenHeight - viewHeight - mYBottomEdgeSize;
} else if (yPosition < mYTopEdgeSize) {
// 当前位置小于允许的上边距,返回最上边距
return mYTopEdgeSize;
} else {
// 展示真实位置
return yPosition;
}
}
public View getRootView() {
return mRootView;
}
public boolean isShow() {
return mIsShow;
}
public void show() {
mIsShow = true;
// 先尝试移除
try {
mLayoutParams.x = getRealX(mLayoutParams.x, false, true);
mLayoutParams.y = getRealY(mLayoutParams.y, false);
mWindowManager.removeView(mRootView);
} catch (Exception e) {
//nothing
}
// 将悬浮窗控件添加到WindowManager
mWindowManager.addView(mRootView, mLayoutParams);
}
public void dismiss() {
// 尝试移除
try {
mWindowManager.removeView(mRootView);
} catch (Exception e) {
//nothing
}
mIsShow = false;
}
private class EFWindowOnTouchListener implements View.OnTouchListener {
private boolean isMoved;
private int oX;
private int oY;
private int x;
private int y;
@Override
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 初始化滑动的标记
isMoved = false;
oX = (int) event.getRawX();
oY = (int) event.getRawY();
x = (int) event.getRawX();
y = (int) event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
int nowX = (int) event.getRawX();
int nowY = (int) event.getRawY();
int movedX = nowX - x;
int movedY = nowY - y;
x = nowX;
y = nowY;
// 如果没有触发滑动,则进行滑动判断
if (!isMoved && (Math.abs(oX - x) > mMinScrollDistance || Math.abs(oY - y) > mMinScrollDistance)) {
isMoved = true;
}
// 拖动中不能用贴边计算
mLayoutParams.x = getRealX(mLayoutParams.x + movedX, false, false);
mLayoutParams.y = getRealY(mLayoutParams.y + movedY, false);
mWindowManager.updateViewLayout(view, mLayoutParams);
break;
case MotionEvent.ACTION_UP:
if (mIsSticky) {
int viewWidth = view.getMeasuredWidth();
int screenWidth = ScreenUtils.getScreenWidth(mContext);
// 贴边终点只有左、右两种状态
if ((mLayoutParams.x + viewWidth / 2) > screenWidth / 2) {
if (mOnPositionListener != null) {
mOnPositionListener.onPositionChanged(OnPositionListener.POSITION_RIGHT);
}
mLayoutParams.x = screenWidth - viewWidth - mXEdgeSize;
} else {
if (mOnPositionListener != null) {
mOnPositionListener.onPositionChanged(OnPositionListener.POSITION_LEFT);
}
mLayoutParams.x = mXEdgeSize;
}
mWindowManager.updateViewLayout(view, mLayoutParams);
}
// 处理移动后还会响应点击事件的情况
if (isMoved) {
isMoved = false;
return true;
}
break;
default:
break;
}
return false;
}
}
public static class Builder {
private final Context mContext;
private View mRootView;
private int mXPosition;
private int mYPosition;
private boolean mCanDrag;
private boolean mIsSticky;
private int mXEdgeSize;
private int mYTopEdgeSize;
private int mYBottomEdgeSize;
private View.OnClickListener mOnClickListener;
private OnPositionListener mOnPositionListener;
public Builder(Context context) {
mContext = context;
}
public Builder onPositionListener(OnPositionListener onPositionListener) {
mOnPositionListener = onPositionListener;
return this;
}
public Builder onClickListener(View.OnClickListener onClickListener) {
mOnClickListener = onClickListener;
return this;
}
public Builder xPosition(int xPosition) {
mXPosition = xPosition;
return this;
}
public Builder yPosition(int yPosition) {
mYPosition = yPosition;
return this;
}
public Builder view(View view) {
mRootView = view;
return this;
}
public Builder canDrag(boolean canDrag) {
mCanDrag = canDrag;
return this;
}
public Builder isSticky(boolean isSticky) {
mIsSticky = isSticky;
return this;
}
public Builder xEdgeSize(int xEdgeSize) {
mXEdgeSize = xEdgeSize;
return this;
}
public Builder yTopEdgeSize(int yTopEdgeSize) {
mYTopEdgeSize = yTopEdgeSize;
return this;
}
public Builder yBottomEdgeSize(int yBottomEdgeSize) {
mYBottomEdgeSize = yBottomEdgeSize;
return this;
}
public Builder view(int viewRes) throws Exception {
if (mContext == null) {
throw new Exception("EFWindow:请传入正确的context.");
}
mRootView = LayoutInflater.from(mContext).inflate(viewRes, null);
return this;
}
@RequiresApi(api = Build.VERSION_CODES.M)
public EFWindow build() throws Exception {
if (mContext == null) {
throw new Exception("EFWindow:请传入正确的context.");
}
if (mRootView == null) {
throw new Exception("EFWindow:请先设置Window布局.");
}
return new EFWindow(this);
}
}
public interface OnPositionListener {
int POSITION_LEFT = 0;
int POSITION_MIDDLE = 1;
int POSITION_RIGHT = 2;
void onPositionChanged(int positionStatus);
}
private boolean isHorizontalScreen(Context context) {
int angle = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
//屏幕旋转90°或270°,表示横屏
return angle == Surface.ROTATION_90 || angle == Surface.ROTATION_270;
}
}
版权声明:
作者:lichengxin
链接:https://www.techfm.club/p/50986.html
来源:TechFM
文章版权归作者所有,未经允许请勿转载。
共有 0 条评论