当前位置: 首页 > news >正文

化妆品电子商务网站开发流程描述房地产公司的网站建设方案

化妆品电子商务网站开发流程描述,房地产公司的网站建设方案,华竣国际的展厅设计公司,烟台网站优化推广目录 1 前言 1.1 准备知识 1.2 问题概述 2 解决方案 3 代码部分 3.1 动态更新窗口焦点 3.2 窗口监听返回事件 3.3 判断焦点是否在窗口内部 3.4 窗口监听焦点移入/移出 4 注意事项 4.1 窗口范围 4.2 空隙处的返回事件处理 1 前言 1.1 准备知识 1)开发环…

目录

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眼镜等增强现实设备。

5)Hover事件分发:当前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 解决方案

        方案主要分为如下几步:

  1. 窗口默认不可获取焦点;
  2. 窗口监听焦点的移入/移出事件;
  3. 窗口监听到焦点移入,判断窗口是否可获取焦点,否——设置窗口可获取焦点,是——不做任何操作;
  4. 窗口监听到焦点移出,判断焦点是否在窗口内部,否——设置窗口不可获取焦点,是——不做任何操作;

        读者可思考如下2个问题,

1)问题1:为什么在窗口监听到焦点移入后,要再判断窗口是否可获取焦点?

2)问题2:为什么在窗口监听到焦点移出后,要再判断焦点是否在窗口内部?

        相信本文《1.1 准备知识的Hover事件分发部分》可以给你一些灵感。   

     

3 代码部分

3.1 动态更新窗口焦点

        核心API:

  • WindowManager.updateViewLayout
  • WindowManager.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还是会接收到返回事件。

那么,如何处理这种空隙处的返回事件呢?

       核心:从系统层拦截此种情况下的返回事件 。

  1. 渲染层:提供接口,返回焦点移入移出时当前layer的名称,是否有碰撞窗口等信息;
  2. 系统层:当没有碰撞窗口时,从系统层拦截掉返回事件的分发;
  3. 应用层:监听焦点移入移出,改变窗口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.15wanjia.com/news/171709.html

相关文章:

  • 网站开发费用如何账务处理东莞网站制作个性化
  • 一学一做演讲视频网站西部域名网
  • wap网站 全屏wordpress type参数
  • 贵阳网站建设策划方案线上营销公司
  • 个人网站 推荐优化设计五年级上册语文答案
  • php怎样做网站管理后台网站搭建好有什么内容可以修改
  • 大庆网站设计wordpress 定期删除
  • 可以做富集分析的网站广东建设继续教育网站
  • 网站绝对地址兰州网站seo收费标准
  • 网站是如何制作的莱芜在线论坛话题牛泉镇
  • 模板手机网站建设电影网站建设方案ppt
  • 校园风险管理网站建设方案seo优化软件有哪些
  • 北京网站建设第一品牌怎么做北京赛车网站
  • 网站建设的总体需求是什么摄影网站建设文案
  • 广州网站公司建设网站建设vip教程
  • 购物网站免费模板开发商虚假宣传怎么赔偿
  • 开网站做代发建设门户网站的公司
  • 网站开发有哪些方式dw网站建设框架大小设定
  • 网站系统管理计划百度应用市场
  • 做公司网站需要会什么科目行业电子商务网站建设
  • 乐清网站制作的公司seo工具是什么意思
  • 调颜色网站wordpress还原明文密码
  • 深圳网站开发报价手机网站怎么做微信登陆
  • 网站建设 美橙泰州网站建设公司哪家好
  • 做网站初始配置wordpress 菜单 导出
  • 济南网站开发公司排名做网站是用啥软件做的
  • 建设网站服务商wordpress 首页显示图片
  • 网站资料上传教程wordpress网校
  • 找个人合伙做网站开源网站统计
  • .net网站做优化哪个平台做推广效果好