化妆品电子商务网站开发流程描述,php wordpress 备份数据库,三亚旅游网站建设,做一个网站怎么做的吗目录
1 前言
1.1 准备知识
1.2 问题概述
2 解决方案
3 代码部分
3.1 动态更新窗口焦点
3.2 窗口监听返回事件
3.3 判断焦点是否在窗口内部
3.4 窗口监听焦点移入/移出
4 注意事项
4.1 窗口范围
4.2 空隙处的返回事件处理 1 前言
1.1 准备知识
1#xff09;开发环…目录
1 前言
1.1 准备知识
1.2 问题概述
2 解决方案
3 代码部分
3.1 动态更新窗口焦点
3.2 窗口监听返回事件
3.3 判断焦点是否在窗口内部
3.4 窗口监听焦点移入/移出
4 注意事项
4.1 窗口范围
4.2 空隙处的返回事件处理 1 前言
1.1 准备知识
1开发环境
2D开发环境所有界面或窗口都在主界面显示3D开发环境保留原生Android的主界面在主界面之外绘制各种窗口配合3D渲染以实现3D效果。
2焦点就是Hover点、中央注视点、可与用户交互的点。
3窗口就是系统窗口、悬浮弹窗内部通过addView方法去添加View本文窗口监听指的就是View监听。
4事件分发Android设备一般会使用如下3种本文采用的第3种setOnHoverListener获取事件。
setOnTouchListener(MotionEvent::InputEvent)手机、平板、车载等屏幕可触控的2D设备setOnKeyListener(KeyEvent::InputEvent)电视、投影仪等屏幕不可触控的2D设备setOnHoverListener(MotionEvent::InputEvent)AR眼镜等增强现实设备。
5Hover事件分发当前View在焦点移出不再是Hover状态时不会立即发送ACTION_HOVER_EXIT退出事件需要等到下一个View获取到ACTION_HOVER_ENTER状态时才会发送上一个View的ACTION_HOVER_EXIT退出事件。
6窗口内部View的Hover事件分发过程
RootView会先获取到ACTION_HOVER_ENTER事件当进入ChildView时ChildView会先获取到ACTION_HOVER_ENTER事件然后RootView会获取到ACTION_HOVER_EXIT事件当从ChildView退出时ChildView会先获取到ACTION_HOVER_EXIT事件然后RootView会获取到ACTION_HOVER_ENTER事件。
1.2 问题概述 问题描述在Android悬浮弹窗上双击返回主界面响应返回事件。 问题原因悬浮弹窗设置了flag为窗口不可获取焦点即WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE。 问题分析
悬浮弹窗设置flag为窗口不可获取焦点是为了不影响主界面的焦点响应Android默认主界面的窗口是获取焦点的如果悬浮弹窗设置flag可获取焦点那么Android的事件分发是无法发送到主界面的会将事件分发给当前可获取焦点的悬浮弹窗如下图左侧图1为悬浮弹窗右侧图2为主界面某应用打开一个Activity。图1悬浮弹窗是常驻于图2主界面的左侧且默认不可获取焦点但在特殊情况时可获取焦点如展开键盘、焦点在此悬浮弹窗内部等情况。 解决方案当焦点在悬浮弹窗内部时设置窗口flag可获取焦点当焦点不在悬浮弹窗内部时设置窗口flag不可获取焦点。 2 解决方案 方案主要分为如下几步
窗口默认不可获取焦点窗口监听焦点的移入/移出事件窗口监听到焦点移入判断窗口是否可获取焦点否——设置窗口可获取焦点是——不做任何操作窗口监听到焦点移出判断焦点是否在窗口内部否——设置窗口不可获取焦点是——不做任何操作 读者可思考如下2个问题
1问题1为什么在窗口监听到焦点移入后要再判断窗口是否可获取焦点
2问题2为什么在窗口监听到焦点移出后要再判断焦点是否在窗口内部 相信本文《1.1 准备知识的Hover事件分发部分》可以给你一些灵感。 3 代码部分
3.1 动态更新窗口焦点 核心API
WindowManager.updateViewLayoutWindowManager.LayoutParams.flags WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE private fun initLiveDataBus() {LiveDataBus.get().with(Constants.NOTIFICATION_EVENT_BUS_FOCUSABLE, Boolean::class.java).observeForever { focusable: Boolean -Log.d(TAG, onChanged: $focusable)updateNotificationParams(focusable)}}private fun updateNotificationParams(focusable: Boolean) {initLayoutParams(focusable)mUiHandler.post {synchronized(this) {if (mIsBarWindowAdded) {try {mWindowManager.updateViewLayout(mNotificationBar, mLayoutParams)} catch (e: Exception) {e.printStackTrace()}}}}}private fun initLayoutParams(focusable: Boolean) {mLayoutParams WindowManager.LayoutParams().apply {type WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAYval density mContext.resources.displayMetrics.densitywidth (640 * density).toInt()height (640 * density).toInt()flags WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH or WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITSif (!focusable) {flags flags or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE}format PixelFormat.RGBA_8888 // 去除默认时有的黑色背景设置为全透明gravity Gravity.TOP or Gravity.STARTtitle SYSUI_NOTIFICATIONx -(640 * density).toInt()y 0}}
3.2 窗口监听返回事件 窗口设置可获得焦点后内部View会获取到事件分发的事件在此View中重写dispatchKeyEvent方法监听keyCode KeyEvent.KEYCODE_BACK事件就可对返回事件进行处理。 override fun dispatchKeyEvent(event: KeyEvent): Boolean {if (event.keyCode KeyEvent.KEYCODE_BACK) {Log.i(TAG, dispatchKeyEvent: KEYCODE_BACK)// 窗口设置可获得焦点后内部View会获取到事件分发的事件并可对返回事件进行处理}return super.dispatchKeyEvent(event)}
3.3 判断焦点是否在窗口内部 通过View相对于屏幕位置X/Y、以及View宽高共同确定View的边界。 mRootView.post {val locationXY IntArray(2)mRootView.getLocationOnScreen(locationXY)val locationX locationXY[0]val locationY locationXY[1]val measuredWidth mRootView.measuredWidthval measuredHeight mRootView.measuredHeight}/*** 焦点就是Hover点、中央注视点、可与用户交互的点。** param locationX View相对于屏幕位置X* param locationY View相对于屏幕位置Y* param measuredWidth View宽* param measuredHeight View高* param rawX 焦点相对于屏幕位置X* param rawY 焦点相对于屏幕位置Y** return 焦点是否未在View内部*/private fun isViewNotFocus(locationX: Int,locationY: Int,measuredWidth: Int,measuredHeight: Int,rawX: Float,rawY: Float) if (rawX locationX || rawX locationX measuredWidth || rawY locationY || rawY locationY measuredHeight) {// 焦点不在View内部Log.i(TAG, isViewNotFocus: 焦点不在View内部)true} else {// 焦点在View内部Log.i(TAG, isViewNotFocus: 焦点在View内部)false}
3.4 窗口监听焦点移入/移出
窗口监听到焦点移入判断窗口是否可获取焦点否——设置窗口可获取焦点是——不做任何操作窗口监听到焦点移出判断焦点是否在窗口内部否——设置窗口不可获取焦点是——不做任何操作最后通过发送NOTIFICATION_EVENT_BUS_FOCUSABLE事件进而设置窗口的是否可获取焦点。 // 注Focus移出时需要包含边界。mRootView.setOnHoverListener { v, event -when (event.action) {MotionEvent.ACTION_HOVER_ENTER - {Log.i(TAG,OnHoverListener: 进入, action ${event.action},motionX ${event.rawX},motionY ${event.rawY})LiveDataBus.get().with(NOTIFICATION_EVENT_BUS_FOCUSABLE).value?.let {if (!(it as Boolean)) {Log.i(TAG, OnHoverListener: 进入, focus-true-again)LiveDataBus.get().with(NOTIFICATION_EVENT_BUS_FOCUSABLE).value true}} ?: let {Log.i(TAG, OnHoverListener: 进入, focus-true-init)LiveDataBus.get().with(NOTIFICATION_EVENT_BUS_FOCUSABLE).value true}}MotionEvent.ACTION_HOVER_MOVE - {}MotionEvent.ACTION_HOVER_EXIT - {Log.i(TAG,OnHoverListener: 退出, action ${event.action},motionX ${event.rawX},motionY ${event.rawY})if (isViewNotFocus(locationX,locationY,measuredWidth,measuredHeight,event.rawX,event.rawY)) {Log.i(TAG, OnHoverListener: 退出, focus-false)LiveDataBus.get().with(NOTIFICATION_EVENT_BUS_FOCUSABLE).value false}}}false} 4 注意事项
4.1 窗口范围 在判断焦点是否在窗口内部时需要确认窗口范围如果窗口内部的View有设置Padding或Margin应该将其去掉。 如本文的窗口大小是640*640但View大小是540*580所以计算时需要去掉相应Padding或Margin重写isViewNotFocus()方法如下 private fun isViewNotFocus(locationX: Int,locationY: Int,measuredWidth: Int,measuredHeight: Int,rawX: Float,rawY: Float): Boolean {val density context.resources.displayMetrics.densityreturn rawX locationX 50 * density || rawX locationX measuredWidth - 100 * density || rawY locationY 15 * density || rawY locationY measuredHeight - 60 * density}
4.2 空隙处的返回事件处理 1从窗口移出到空隙处 通过本文1.1准备知识的第5部分《Hover事件分发》我们知道从窗口移出但还未有下一个View获取焦点时此时窗口还是会接收到返回事件。 2从View移出到空隙处 从当前View移出但还未有下一个View获取焦点时此时当前View还是会接收到返回事件。 那么如何处理这种空隙处的返回事件呢 核心从系统层拦截此种情况下的返回事件 。 渲染层提供接口返回焦点移入移出时当前layer的名称是否有碰撞窗口等信息系统层当没有碰撞窗口时从系统层拦截掉返回事件的分发应用层监听焦点移入移出改变窗口focus属性并处理返回事件
解决方案 当空隙处有返回事件产生时系统层通过渲染层的接口获取到当前焦点所在位置的layer名称如果layer名称为空则断定为空隙处直接做拦截处理不再往应用层分发。 注每个窗口、Activity在其Window中都有设置其title属性layer名称就是此title属性的值。 目录
1 前言
1.1 准备知识
1.2 问题概述
2 解决方案
3 代码部分
3.1 动态更新窗口焦点
3.2 窗口监听返回事件
3.3 判断焦点是否在窗口内部
3.4 窗口监听焦点移入/移出
4 注意事项
4.1 窗口范围
4.2 空隙处的返回事件处理 文章转载自: http://www.morning.sflnx.cn.gov.cn.sflnx.cn http://www.morning.zstry.cn.gov.cn.zstry.cn http://www.morning.xnwjt.cn.gov.cn.xnwjt.cn http://www.morning.gmjkn.cn.gov.cn.gmjkn.cn http://www.morning.hmsong.com.gov.cn.hmsong.com http://www.morning.qwhbk.cn.gov.cn.qwhbk.cn http://www.morning.jzccn.cn.gov.cn.jzccn.cn http://www.morning.zlqyj.cn.gov.cn.zlqyj.cn http://www.morning.dthyq.cn.gov.cn.dthyq.cn http://www.morning.mtgkq.cn.gov.cn.mtgkq.cn http://www.morning.drcnf.cn.gov.cn.drcnf.cn http://www.morning.rkzb.cn.gov.cn.rkzb.cn http://www.morning.rfhm.cn.gov.cn.rfhm.cn http://www.morning.fzwf.cn.gov.cn.fzwf.cn http://www.morning.tqrbl.cn.gov.cn.tqrbl.cn http://www.morning.llcsd.cn.gov.cn.llcsd.cn http://www.morning.rlnm.cn.gov.cn.rlnm.cn http://www.morning.wgkz.cn.gov.cn.wgkz.cn http://www.morning.smtrp.cn.gov.cn.smtrp.cn http://www.morning.qczpf.cn.gov.cn.qczpf.cn http://www.morning.lfgql.cn.gov.cn.lfgql.cn http://www.morning.jkpnm.cn.gov.cn.jkpnm.cn http://www.morning.mrfr.cn.gov.cn.mrfr.cn http://www.morning.lrjtx.cn.gov.cn.lrjtx.cn http://www.morning.mhpmw.cn.gov.cn.mhpmw.cn http://www.morning.yrpg.cn.gov.cn.yrpg.cn http://www.morning.rpsjh.cn.gov.cn.rpsjh.cn http://www.morning.ypfw.cn.gov.cn.ypfw.cn http://www.morning.sxtdh.com.gov.cn.sxtdh.com http://www.morning.fdrwk.cn.gov.cn.fdrwk.cn http://www.morning.lcbgf.cn.gov.cn.lcbgf.cn http://www.morning.wbqt.cn.gov.cn.wbqt.cn http://www.morning.hyxwh.cn.gov.cn.hyxwh.cn http://www.morning.brzlp.cn.gov.cn.brzlp.cn http://www.morning.hhfqk.cn.gov.cn.hhfqk.cn http://www.morning.bxqtq.cn.gov.cn.bxqtq.cn http://www.morning.thpzn.cn.gov.cn.thpzn.cn http://www.morning.c7507.cn.gov.cn.c7507.cn http://www.morning.fnxzk.cn.gov.cn.fnxzk.cn http://www.morning.bnlkc.cn.gov.cn.bnlkc.cn http://www.morning.rxhs.cn.gov.cn.rxhs.cn http://www.morning.dyxlm.cn.gov.cn.dyxlm.cn http://www.morning.tbksk.cn.gov.cn.tbksk.cn http://www.morning.xbptx.cn.gov.cn.xbptx.cn http://www.morning.rwqk.cn.gov.cn.rwqk.cn http://www.morning.qqnp.cn.gov.cn.qqnp.cn http://www.morning.pzlcd.cn.gov.cn.pzlcd.cn http://www.morning.bzsqr.cn.gov.cn.bzsqr.cn http://www.morning.fsqbx.cn.gov.cn.fsqbx.cn http://www.morning.lmqfq.cn.gov.cn.lmqfq.cn http://www.morning.lwdzt.cn.gov.cn.lwdzt.cn http://www.morning.lpqgq.cn.gov.cn.lpqgq.cn http://www.morning.ffbl.cn.gov.cn.ffbl.cn http://www.morning.prmbn.cn.gov.cn.prmbn.cn http://www.morning.slwfy.cn.gov.cn.slwfy.cn http://www.morning.yuanshenglan.com.gov.cn.yuanshenglan.com http://www.morning.ghxzd.cn.gov.cn.ghxzd.cn http://www.morning.wrwcf.cn.gov.cn.wrwcf.cn http://www.morning.abgy8.com.gov.cn.abgy8.com http://www.morning.wdjcr.cn.gov.cn.wdjcr.cn http://www.morning.trkl.cn.gov.cn.trkl.cn http://www.morning.cfcdr.cn.gov.cn.cfcdr.cn http://www.morning.mprtj.cn.gov.cn.mprtj.cn http://www.morning.iuibhkd.cn.gov.cn.iuibhkd.cn http://www.morning.mxxsq.cn.gov.cn.mxxsq.cn http://www.morning.wfcqr.cn.gov.cn.wfcqr.cn http://www.morning.cwskn.cn.gov.cn.cwskn.cn http://www.morning.hlxxl.cn.gov.cn.hlxxl.cn http://www.morning.bfbl.cn.gov.cn.bfbl.cn http://www.morning.rshijie.com.gov.cn.rshijie.com http://www.morning.pqjpw.cn.gov.cn.pqjpw.cn http://www.morning.bhgnj.cn.gov.cn.bhgnj.cn http://www.morning.nrwr.cn.gov.cn.nrwr.cn http://www.morning.lphtm.cn.gov.cn.lphtm.cn http://www.morning.yqpck.cn.gov.cn.yqpck.cn http://www.morning.qkdjq.cn.gov.cn.qkdjq.cn http://www.morning.rfwgg.cn.gov.cn.rfwgg.cn http://www.morning.qyllw.cn.gov.cn.qyllw.cn http://www.morning.prjns.cn.gov.cn.prjns.cn http://www.morning.cxryx.cn.gov.cn.cxryx.cn