当前位置:网站首页>判断View滑入或滑出屏幕可见区
判断View滑入或滑出屏幕可见区
2022-07-20 13:40:00 【OpenLD】
今天在用今日头条app的时候发现了一个现象,比如你正在看视频(未全屏),此时上下滑动使得视频滑出屏幕可见区,那刚才正在播放的视频就自动暂停了。
这里思考下,肯定有某种方式能够知道View是否在屏幕可见区,于是我就去View类中找了下,发现没有直接的监听器。但是有这样一个方法:
public final boolean getGlobalVisibleRect(Rect r) {
return getGlobalVisibleRect(r, null);
}
往里面走:
/**
* If some part of this view is not clipped by any of its parents, then
* return that area in r in global (root) coordinates. To convert r to local
* coordinates (without taking possible View rotations into account), offset
* it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
* If the view is completely clipped or translated out, return false.
*
* @param r If true is returned, r holds the global coordinates of the
* visible portion of this view.
* @param globalOffset If true is returned, globalOffset holds the dx,dy
* between this view and its root. globalOffet may be null.
* @return true if r is non-empty (i.e. part of the view is visible at the
* root level.
*/
public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
int width = mRight - mLeft;
int height = mBottom - mTop;
if (width > 0 && height > 0) {
r.set(0, 0, width, height);
if (globalOffset != null) {
globalOffset.set(-mScrollX, -mScrollY);
}
return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
}
return false;
}
这里重点关注下注释,当返回为true时,代表View在全局坐标中有可见的部分。那其实就是说,当该方法返回为true的时后说明该View的部分或者全部在屏幕可见区域,返回false的时候则该View完全不在屏幕可见区域。当返回为true的时候,该View在屏幕中的可见区域信息保存在名为r的Rect对象中。
那就明白了,其实Google早就想到了我们的使用场景,通过这种方式来让我们知道View到底是滑入了屏幕可见区域还是滑出了屏幕可见区域。
之后我来写个Demo验证一下,布局非常简单。
最外层是个可以垂直滑动的NestedScrollView,里面填满ConstraintLayout,约束布局里面首尾都是一个较高的颜色块,中间夹着一张图片。我们的目的就是看在滑动中这张图片进入屏幕离开屏幕调用getGlobalVisibleRect()方法时的表现。
整体布局如下:
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:orientation="vertical"
tools:context=".testviewexposure.TestViewExposureActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:id="@+id/view_top"
android:layout_width="0dp"
android:layout_height="1000dp"
android:background="@color/purple"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/img"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="@drawable/fruit_image6"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/view_top" />
<View
android:id="@+id/view_bottom"
android:layout_width="0dp"
android:layout_height="1000dp"
android:background="@color/green"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/img" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
然后页面代码如下,主要看滑动监听中的情况即可,在关键处打印了日志。
package com.openld.seniorui.testviewexposure
import android.graphics.Rect
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.widget.ImageView
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.core.widget.NestedScrollView
import com.openld.seniorui.R
class TestViewExposureActivity : AppCompatActivity() {
private lateinit var mScrollView: NestedScrollView
private lateinit var mImg: ImageView;
private var mImgWidth = 0
private var mImgHeight = 0
private var mImgArea = 0
private var mRect = Rect()
@RequiresApi(Build.VERSION_CODES.M)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test_view_visible)
initWidgets()
addListeners()
mImg.post {
mImgWidth = mImg.width
mImgHeight = mImg.height
mImgArea = mImgHeight * mImgWidth
Log.d(
"Exposure >>>>>>",
"图片宽度为 ${mImgWidth} 高度为${mImgHeight} 面积为${mImgArea}"
)
}
}
@RequiresApi(Build.VERSION_CODES.M)
private fun addListeners() {
mScrollView.setOnScrollChangeListener { v, scrollX, scrollY, oldScrollX, oldScrollY ->
val isGlobalVisible = mImg.getGlobalVisibleRect(mRect)
if (isGlobalVisible) {
// 有些场景进来是要可见面积大于自身面积的五分之一
// 出去是要可见面积小于自己面积的五分之一
// 这个时候可使用mRect和本身组件的原始面积进行一些比较,这里略
Log.d(
"Exposure >>>>>>",
"全局可见 可见宽度为 ${mRect.width()} 可见高度为${mRect.height()} 可见面积为${mRect.width() * mRect.height()}"
)
} else {
Log.d(
"Exposure >>>>>>",
"全局不可见}"
)
}
}
}
@RequiresApi(Build.VERSION_CODES.M)
private fun initWidgets() {
mScrollView = findViewById(R.id.scroll_view)
mImg = findViewById(R.id.img)
}
}
然后启动一下app,滑动到图片出现再把图片滑出屏幕。
看下对应的logcat日志如下:
1.图片未滑入屏幕
2.图片滑入屏幕中
3.图片完全滑入屏幕
4.图片滑出屏幕中
5.图片完全滑出屏幕
由此可见,遇到问题可以先去对应的类中ctrl+f12键看看类中对应的各种public方法,说不定就能找到需要的方法或者发现一些你不知道的好用的API。
结合着这个API的功能,你完全可以发散着做出很多效果。比如曝光埋点时候你肯定要知道组件何时滑入屏幕何时滑出屏幕。比如做视频播放时,滑出屏幕时候暂停或者回收资源。比如滑出屏幕就停止动画,滑入屏幕才播放动画等等场景。可以举一反三,灵活运用。
边栏推荐
- 淘宝/天猫同款商品搜索API接口详细演示
- JS 将伪数组转换成数组
- 回溯法相关应用实例——素数环问题
- windows安全加固--关闭非必要端口
- 六.uniapp[闪屏页加载方式、闪屏页设置]
- How to solve the RSA public key not find problem in Navicat
- App automated Test-5 Touch screen operation and toast processing
- 路径寻找问题(暴力求解法)例题分析
- Navicat出现Rsa Public Key not Find问题如何解决
- Explain the tax arrears with deduction: there is no tax arrears, and we will continue to operate in compliance as usual
猜你喜欢
业务出海,灵感乍现前要先「把手弄脏」
Android kotlin uses arouter componentized routing and datastore to save data instead of SharedPreferences
APP自动化测试-2. Appium录制测试用例
设计微服务安全架构
7天交付沈阳方舱医院项目,这就是鸿雁速度
密码输入框And优惠券And自定义软键盘
行业现状令人失望,工作之后我又回到UC伯克利读博了
Window进入别的目录
ython中if __name__ == ‘__main__‘:的作用和原理
四.uni-app组件[视图组件、基本内容(官方自带例如表单类)、UI组件库、组件库的坑]
随机推荐
关于let变量提升的问题
【upload靶场17-21】二次渲染、条件竞争、黑白名单绕过
HJ107 solve cube root
Programmer Lao Wang names his children
路径寻找问题(状态空间搜索)
基于CLIP的色情图片识别;油管最新ML课程大合集;交互式编写shell管道;机器人仓库环境增量感知数据集;最新AI论文 | ShowMeAI资讯日报
六石管理学:流程只是便于推脱责任,对解决问题无帮助
设计微服务安全架构
自己整理一些散的知识点
leetcode:730. 统计可以生成多少个不同回文子序列
Deliver Shenyang fangcang hospital project in 7 days, which is Hongyan speed
微服务中*.iml文件删除
网易游戏 Flink SQL 平台化实践
罗敏成不了董宇辉
Vi Uniapp[flash page loading method, flash page settings]
MATLAB basic grammar (I)
乐扣乐扣澄清欠税事件:不存在欠税,将一如既往合规经营
Klocwork部署的安全最佳实践
In microservices * IML file deletion
面试题