高级-UI-从零到整-(一)-View-的基础知识你必须知道

这篇具有很好参考价值的文章主要介绍了高级-UI-从零到整-(一)-View-的基础知识你必须知道。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  • getX / getY : 返回相对于当前 View 左上角的 x 和 y 的坐标
  • getRawX / getRawY : 返回的是相对于手机屏幕左上角的 x 和 y 坐标。

TouchSlop

TouchSlop 官方解释就是系统所能识别的被认为是滑动的最小距离,通俗点说就是当手指在屏幕上滑动时,如果两次滑动之间的距离小于这个常量,那么系统就认为你没有在滑动,可以通过下面的 API 获取该常量值,

/**

  • 系统所能识别出来的被认为滑动的最小距离
    */
    val scaledDoubleTapSlop = ViewConfiguration.get(context).scaledDoubleTapSlop;
    复制代码

这个常量可以帮助我们在处理滑动时,利用该数值来做一些过滤,比如当两次滑动事件的滑动距离小于这个值,我们就可以未达到滑动距离的临界点,因此就可以认为他们不是滑动,这样做可以有更好的用户体验。

VelocityTracker 、GestureDetector 和 Scroller

VelocityTracker

VelocityTracker 的作用是用于追踪滑动过程中的速度,包括水平和竖直方向的速度。它的使用过程很简单,首先,在 View 的 onTouchEvent 方法中追踪当前单击事件的速度;

/**

  • 速度追踪
    */
    val velocityTracker = VelocityTracker.obtain()
    velocityTracker.addMovement(event)
    复制代码

接着,当我们先知道当前的滑动速度时,这个时候可以采用如下方式来获得当前的速度:

velocityTracker.computeCurrentVelocity(1000)
val xVelocity = velocityTracker.getXVelocity()
val yVelocity = velocityTracker.getYVelocity()
复制代码

这一步有 2 点需要注意,其一 获取速度之前必须先计算速度,既 getXVelocity 和 getYVelocity 这两个方法的前面必须要调用 computeCurrentVelocity 方法,第二点,这里的速度是指一段时间内手指所滑过的像素值,比如将时间间隔设为 1000 ms 时,那么就是在 1s 内手指在水平方向从左向右滑动 500 px 那么水平速度就是 500,注意速度可以为负数,当手指从右往左滑动时,水平方向速度即为负值,这个需要理解一下。速度的计算可以用如下公式:

速度 = ( 终点位置 - 起点位置) / 时间段

根据上面的公式再加上 Android 系统的坐标体系,可以知道,手指逆着坐标系的正方向滑动,所产生的速度就为负值,另外,computeCurrentVelocity 这个方法的参数表示的是一个时间单元或者说时间间隔,它的单位是毫秒 (ms), 计算速度时得到的速度就是在这个时间间隔内手指在水平或竖直方向上所滑动的像素值。

针对上面的例子,如果我们通过 obtain.computeCurrentVelocity(1000) 来获取速度,那么得到的速度就是手指在 1000 ms 毫秒内所滑过的 px 值,因此可以直接套上面公式:

水平速度 = 500 px / 每 1000 ms

既水平速度为 500 , 这里需要好好理解一下。

最后,当不需要它的时候,需要调用 clear 方法来重置并回收内存:

velocityTracker.clear()
velocityTracker.recycle()
复制代码

VelocityTracker 的 API 简单明了,我们可以记住一个套路。

  1. 在触摸事件为 ACTION_DOWN或是进入 onTouchEvent方法时,通过 obtain获取一个 VelocityTracker
  2. 在触摸事件为 ACTION_UP时,调用 recycle进行释放 VelocityTracker
  3. 在进入 onTouchEvent方法或将 ACTION_DOWNACTION_MOVEACTION_UP的事件通过 addMovement方法添加进 VelocityTracker
  4. 在需要获取速度的地方,先调用 computeCurrentVelocity方法,然后通过 getXVelocitygetYVelocity获取对应方向的速度

解锁更多姿势可以参考该文章

GestureDetector

GestureDetector 的作用用于辅助检测用户的单机、滑动、长按、双击等行为。要使用 GestureDetector 也不复杂,参考如下过程:

  1. 首先创建一个 GestureDetector 对象并实现 OnGestureListener 接口,根据需要我们还可以实现 OnDoubleTapListener 从而能够监听双击行为;

val mGetDetector = GestureDetector(context,this)
//解决长按屏幕后无法拖动的现象
mGetDetector.setIsLongpressEnabled(false)
复制代码

  1. 接管目前 View 的 onTouchEvent 方法,在 View 的 onTouchEvent 方法中添加如下代码:

override fun onTouchEvent(event: MotionEvent) = mGetDetector.onTouchEvent(event)
复制代码

做完了上面这 2 步,我们就可以有选择的实现 OnGestureListener 和 OnDoubleTapListener 中的方法了,这 2 个接口中的方法介绍如下所示:

OnGestureListener / 方法名 描述
onDown 手指轻轻触摸屏幕的一瞬间,由 1 个 ACTION_DOWN 触发
onShowPress 手指轻轻触摸屏幕, 尚未松开或拖动,由一个 ACTION_DOWN 触发,它强调的是没有松开或者拖动的状态
onSingleTapUp 手指(轻轻触摸屏幕后)松开,伴随着 1 个 MotinEvent.ACTION_UP 而触发,这是单击行为
onScroll 手指按下屏幕并拖动,由 1 个 ACTION_DOWN ,多个 ACTION_MOVE 触发,这是拖动行为
onLongPress 用户长久的按着屏幕不放,既长按
onFling 用户按下触摸屏、快速滑动后松开,由 1 个 ACTION_DOWN 、多个 ACTION_MOVE 和 1 个 ACTION_UP 触发,这是快速滑动行为
OnDoubleTapListener / 方法名 描述
onDoubleTap 双击,由 2 次连续的单击组成,它不可能和 onSingleTapConfirmed 共存
onSingleTapConfirmed 严格的单机行为(注意它和 onSingleTapUp 的区别,如果触发了 onSingleTapConfirmed, 那么后面不可能再紧跟着另一个单击行为,既这只可能是单击,而不可能是双击中的一次单击)
onDoubleTapEvent 表示发生了双击行为,在双击的期间, ACTION_DOWN 、ACTION_MOVE 和 ACTION_UP 都会触发此回调

上面图表里面的方法很多,但是并不是所有的方法都会被时常用到,在日常开发中,比较常用的有 onSingleTapUp 单击、onFling 快速滑动 、onScroll 拖动 、onLongPress 长按、onDoubleTap 双击 。另外在说一下,在实际开发中,可以不使用 GestureDector, 完全可以自己在 View 的 OnTouchEvent 方法中实现所需要的监听,这个看实际场景跟个人喜好了。

Scroller

Scroller 用于实现 View 的弹性滑动。我们知道,当使用 View 的 scrollTo / scrollBy 方法进行滑动时,其过程是瞬间完成的,没有一个过渡的效果体验是不友好的,那么这个时候就可以借助 Scroller 来实现过渡效果的滑动。Scroller 本身无法让 View 弹性滑动,它需要和 View 的 computeScroll 方法配合使用才能共同完成这个功能。那么如何使用 Scroller 呢?它的典型代码可以说是固定的,如下所示:

class ScrollerSample_1 : LinearLayout {

constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)

constructor(context: Context) : super(context)

/**

  • 定义滑动 Scroller
    */
    private val mScroller = Scroller(context)

public fun smoothScrollTo(destX: Int = -100, destY: Int = -100) {
//滑动了的位置
val scrollX = scrollY;
val delta = destY - scrollY;
//2000 ms 内滑动到 destX 位置,效果就是缓慢滑动
mScroller.startScroll(scrollX, 0, 0, delta, 2000)
invalidate()
}

override fun computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.currX, mScroller.currY)
postInvalidate()
}
}
}
复制代码

主要实现有 3 步:

  • 第一步实例化 Scroller

  • 第一步调用 Scroller 的 startScroll 方法,让其内部保存新的变量值

  • 第二步重写 View 的 computeScroll 方法,调度自身的 scrollTo 方法,让其缓慢弹性滑动

View 的滑动

上面咱们介绍了 View 的一些基本知识和一些位置参数概念,该小节将来介绍一个重要的内容 View 的滑动

现在市面上所有软件应该几乎都具备滑动的功能吧?可以说滑动功能是一个 APP 的标配,滑动在 Android 开发中具有很重要的作用,因此,掌握滑动的方法是实现优化用户体验的基础。滑动可以通过以下三种方式来实现,当然并不是只有三种,其它还得靠自己去挖掘。其方式如下:

  1. 通过 View 本身提供的 scrollTo / scrollBy 方法来实现滑动(上一小节咱们已经用到 scrollTo 方法了)
  2. 通过动画给 View 施加平移效果来实现滑动
  3. 通过改变 View 的位置参数

scrollTo、scrollBy

为了实现 View 的滑动看,自身专门提供了 scrollTo 和 scrollBy 方法来实现,如下所示:

//View.java
public void scrollTo(int x, int y) {
/**

  • 传入的位置跟自己目前所滑动的位置不一致才开始滑动
    */
    if (mScrollX != x || mScrollY != y) {
    int oldX = mScrollX;
    int oldY = mScrollY;
    mScrollX = x;
    mScrollY = y;
    invalidateParentCaches();
    onScrollChanged(mScrollX, mScrollY, oldX, oldY);
    if (!awakenScrollBars()) {
    postInvalidateOnAnimation();
    }
    }
    }

public void scrollBy(int x, int y) {
/**

  • 其内部也是调用了 View 的 scrollTo 方法,把当前滑动的 mScrollX,mScrollY 分别加上指定的位 * 置,然后滑动,多次调用相当于接着上一次位置滑动
    */
    scrollTo(mScrollX + x, mScrollY + y);
    }

通过上面的源码我们知道 scrollBy 方法内部是调用了 scrollTo 方法,那么他们之前有什么区别呢?请看下面分析:

scrollTo: 基于所传递的 x , y 坐标来进行绝对滑动,重复点击如果不改变滑动参数,那么内部就会做判断,相等就不会再滑动了。

scrollBy: 通过源码我们知道内部调用了 scrollTo 方法传递了 mScrollX + x, mScrollY + y 那么这是什么意思呢?其实就是基于当前的位置来做的相对滑动。重复点击滑动会继续在当前所在的位置上继续滑动。

还有一个知识点我们要知道,就是这里出现了 2 个默认的变量 mScrollX , mScrollY 通过 scrollTo 内部实现我们知道,其传递进去的 x,y 分别赋值给了 mScrollX 和 mScrollY 那么它们在这里这么做的具体含义是什么呢?它们可以通过 getScrollX 和 getScrollY 来获取具体的值。下面我们就来具体分析下:

mScrollX: 在滑动过程中,mScrollX 的值总是等于 View 左边缘和 View 内容左边缘在水平方向的距离。并且当 View 左边缘在 View 内容左边缘的右边时, mScrollX 值为正,反之为负,通俗的来讲就是如果从左向右滑动,那么 mScrollX 为 负值,反之为正值。

mScrollY: 在滑动过程中,mScrollY 的值总是等于 View 上边缘和 View 内容上边缘在水平方向的距离。并且当 View 上边缘在 View 内容上边缘下边时,mScrollY 为正,反之为负,通俗的来讲就是如果从上往下滑动,那么 mScrollY 为负值,反之为正值。

上面解释了这么多,为了更好的理解我这里就画一张水平跟竖值方向都滑动了 100 px, 然后来看对应的 mScrollX 和 mScrollY 值是多少,请看下图:

高级-UI-从零到整-(一)-View-的基础知识你必须知道,2024年程序员学习,ui

注意: 在使用 scrollBy / scrollTo 对 View 滑动时,只能将 View 的内容进行移动,并不能将 View 本身进行移动。

使用动画

上一小节我们知道可以采用 View 自身的 scrollTo / scrollBy 方法来实现滑动功能,本小节介绍另外一个实现滑动的方式,即使用动画,通过动画我们能够让一个 View 进行平移,而平移就是一种滑动。使用动画来移动 View ,主要是操作 View 的 translationX 和 translationY 属性,可以采用传统的 View 动画,也可以使用属性动画,如果采用属性动画注意要兼容 3.0 一下版本,当然现在都 androidX 版本了,可以看实际项目情况来具体处理,实现滑动的平移代码如下:

  1. 采用 View 动画,将 View 在 100ms 内从原始位置向右下角移动 100 px
<?xml version="1.0" encoding="utf-8"?>

<set xmlns:android=“http://schemas.android.com/apk/res/android”
android:fillAfter=“true”



复制代码

注意: View 动画并不能真正改变 View 的位置。

  1. 采用属性动画,将 View 在 100ms 内从原始位置向右平移 100 px

//动画属性有 translationX 、translationY 、alpha 、rotation、rotationX、rotationY 、scaleX、scaleY
val objAnimator = ObjectAnimator.ofFloat(View targetView,“translationX”,0f,100f).setDuration(100).start()
复制代码

改变 View LayoutParams

本小节将介绍第三种实现 View 滑动的方法,那就是直接改变布局参数,即 LayoutParams。比如我们想把一个 LinearLayout 向右平移 100px 只需要将它的 LayoutParams 内部的 marginLeft 参数的值增加 100 px 就行,代码如下:

val layoutParams = scroller.layoutParams as LinearLayout.LayoutParams
layoutParams.let {
it.leftMargin += 100
it.weight += 100
}
scroller.requestLayout()
复制代码

通过改变 LinearLayout 的 LayoutParams 参数同样也实现了 View 的滑动。

滑动方式对比

上面分别介绍了 3 种不同的滑动方式,它们都能实现 View 的滑动,那么它们之间的差异是什么呢?请看下表:

实现方式 优点 缺点
scrollTo/scrollBy 专门用于 View 的滑动,比较方便地实现滑动效果且不影响自身的单机事件 只能滑动 View 的内容,不能滑动 View 本身
动画 复杂动画使用属性动画来完成比较简单 View 动画不能改变自身属性
改变布局参数 使用不简洁

针对上面情况这里做一个小总结:

  • scrollTo/scrollBy 操作简单,适合对 View 内容的滑动
  • 动画操作简单,主要适合用于没有交互的 View 和实现复杂的动画效果
  • 改变布局参数操作稍微复杂,适用于有交互的 View

弹性滑动

知道了 View 如何滑动,我们还要知道如何实现 View 的弹性滑动,比较生硬的滑动体验确实很差,下面我们介绍 View 如何实现弹性滑动

使用 Scroller

请参考该篇 View基础知识#Scroller 介绍

通过动画

高级-UI-从零到整-(一)-View-的基础知识你必须知道,2024年程序员学习,ui

利用动画的特性来实现一些动画不能实现的效果,模仿 Scroller 来实现 View 的弹性滑动,代码如下:

val valueAnimator = ValueAnimator.ofInt(0, 1).setDuration(2000);
valueAnimator.addUpdateListener {
val animatedFraction = it.animatedFraction
scroller.scrollTo(- (100 * animatedFraction).toInt(), 0)
}
valueAnimator.start()

在上述代码中,我们的动画本质上没有作用于任何对象上,它只是在 2s 内完成了整个动画过程,利用这个特性我们就可以在动画的每一帧到来时获取动画完成的比例,然后根据这个比例计算滑动的距离。

通过延时策略

该小节我们继续介绍另一种实现弹性滑动的效果,即延时策略,它的核心思想是通过发送一系列延时消息从而达到一种渐近式的效果,代码如下:

val MESSAGE_SCROLLER_TO = 1;
val FRAME_COUNT = 30;
val DELAYED_TIME = 33L;
var mCount = 0;
private val mHandler = object : Handler() {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
when (msg.what) {
MESSAGE_SCROLLER_TO -> {
mCount++
if (mCount <= FRAME_COUNT) {

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
高级-UI-从零到整-(一)-View-的基础知识你必须知道,2024年程序员学习,ui
高级-UI-从零到整-(一)-View-的基础知识你必须知道,2024年程序员学习,ui
高级-UI-从零到整-(一)-View-的基础知识你必须知道,2024年程序员学习,ui
高级-UI-从零到整-(一)-View-的基础知识你必须知道,2024年程序员学习,ui
高级-UI-从零到整-(一)-View-的基础知识你必须知道,2024年程序员学习,ui
高级-UI-从零到整-(一)-View-的基础知识你必须知道,2024年程序员学习,ui
高级-UI-从零到整-(一)-View-的基础知识你必须知道,2024年程序员学习,ui

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
高级-UI-从零到整-(一)-View-的基础知识你必须知道,2024年程序员学习,ui

【附】相关架构及资料

高级-UI-从零到整-(一)-View-的基础知识你必须知道,2024年程序员学习,ui

高级-UI-从零到整-(一)-View-的基础知识你必须知道,2024年程序员学习,ui

往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算文章来源地址https://www.toymoban.com/news/detail-859144.html

构视频+大厂面试真题+项目实战源码》]( )收录**

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

到了这里,关于高级-UI-从零到整-(一)-View-的基础知识你必须知道的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 从零开始-学习网络必须掌握的基础知识

    从零开始!学习网络必须掌握的基础知识 完整的100个网络知识,可留言,会发送!点击关注,可获得网工大礼包哈

    2024年02月15日
    浏览(43)
  • 线性代数之美:从基础知识到高级技巧

    线性代数是数学的一个分支,它研究的是线性方程组和线性空间等概念。线性代数在许多科学和工程领域都有广泛的应用,例如机器学习、计算机图形学、信号处理等。在这篇文章中,我们将从基础知识到高级技巧来详细讲解线性代数的核心概念、算法原理、具体操作步骤以

    2024年01月20日
    浏览(39)
  • 深入理解 C++ 语法:从基础知识到高级应用

    让我们将以下代码分解以更好地理解它: 示例 示例解释 第 1 行: #include iostream 是一个头文件库,它让我们可以使用输入和输出对象,比如 cout (在第 5 行使用)。头文件为 C++ 程序添加功能。 第 2 行: using namespace std 表示我们可以使用标准库中的对象和变量名称。 如果你

    2024年03月23日
    浏览(34)
  • 使用 Python 中的 Langchain 从零到高级快速进行工程

    大型语言模型 (LLM) 的一个重要方面是这些模型用于学习的参数数量。模型拥有的参数越多,它就能更好地理解单词和短语之间的关系。这意味着具有数十亿个参数的模型有能力生成各种创造性的文本格式,并以信息丰富的方式回答开放式和挑战性的问题。 ChatGPT 等法学硕士利

    2024年02月13日
    浏览(26)
  • 突破编程_C++_高级教程(模板编程的基础知识)

    C++ 的模板编程是一种编程技术,它允许程序员编写处理不同类型数据的通用代码。通过使用模板,可以创建与特定数据类型无关的函数或类,这些函数或类在编译时可以根据需要生成特定数据类型的版本。这增加了代码的复用性、灵活性和类型安全性。 从本质上来说, C++

    2024年02月19日
    浏览(32)
  • C++ Webserver从零开始:基础知识(三)——Linux服务器程序框架

    目录 前言 一.服务器编程基础框架 C/S模型 主要框架 二.I/O模型 阻塞I/O 非阻塞I/O 异步I/O 三.两种高效的事件处理模式 Reactor Proactor 四.模拟Proactor模式 五.半同步/半异步的并发模式 六.有限状态机 七.其他提高服务器性能的方法 池 数据复制 上下文切换和锁         这一章是

    2024年02月22日
    浏览(40)
  • C++ 字符串完全指南:学习基础知识到掌握高级应用技巧

    字符串用于存储文本。 一个字符串变量包含由双引号括起来的一组字符: 示例 创建一个 string 类型的变量并为其赋值: 字符串连接可以使用 + 运算符来实现,生成一个新的字符串。 示例: 在上面的示例中,我们在 firstName 后面添加了一个空格,以便在输出时在 \\\"John\\\" 和 \\\"D

    2024年04月08日
    浏览(42)
  • 软考高级系统架构设计师(三) 基础知识之操作系统1进程

    目录 概要  操作系统 概述 ​编辑 进程管理 进程的状态  进程管理-PV操作 利用PV操作实现进程的同步  进程管理-前趋图  进程管理-死锁 操作系统的功能: 进程管理、存储管理、文件管理、作业管理、设备管理 操作系统的特征 并发性 共享性 虚拟性 不确定性   进程是程序

    2024年02月10日
    浏览(29)
  • Rust 全面指南:从基础到高级,一网打尽 Rust 的编程知识

    因为在学习Rust过程中,因为代码量不是太多,所以有一些学完就忘了,特此记录一些Rust知识点 Rust是什么? Rust是一种现代的、强类型的、系统级编程语言。它被设计用于编写高性能、并发、安全的系统,并且可以避免常见的内存安全问题,如空指针和数据竞争。Rust的特点包

    2024年02月08日
    浏览(38)
  • 【Flutter·学习实践·UI篇】基础且重要的UI知识

    参考学习官网:《Flutter实战·第二版》  学习前先记住:Flutter 中万物皆为Widget,心中默念3次以上铭记于心。 这一点和开发语言Dart的变量一切皆是对象的概念,相互对应。 在前面的介绍中,我们知道在Flutter中几乎所有的对象都是一个 widget 。与原生开发中“控件”不同的是

    2024年02月15日
    浏览(24)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包