View的滑动之ScrollTo和ScrollBy

2024-02-13 19:08
文章标签 view 滑动 scrollto scrollby

本文主要是介绍View的滑动之ScrollTo和ScrollBy,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目前View滑动的实现方式主要有三种:

1.通过View自身提供的ScrollTo和ScrollBy。

2.通过动画来使View平移来实滑动。

3.第三种是通过改变View的LayoutParams,使View重新布局实现滑动。

这几天在看View的滑动,虽然ScrollTo和ScrollBy在实际的开发过程中用到的很少,特别是属性动画的广泛运用后,既然存在,必有价值。

所以在这里将ScrollTo和ScrollBy简单分析一下:


先看一下ScrollTo的源码:

/*** Set the scrolled position of your view. This will cause a call to* {@link #onScrollChanged(int, int, int, int)} and the view will be* invalidated.* @param x the x position to scroll to* @param y the y position to scroll to*/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();}}}
再看看ScrollBy的源码:

/*** Move the scrolled position of your view. This will cause a call to* {@link #onScrollChanged(int, int, int, int)} and the view will be* invalidated.* @param x the amount of pixels to scroll by horizontally* @param y the amount of pixels to scroll by vertically*/public void scrollBy(int x, int y) {scrollTo(mScrollX + x, mScrollY + y);}

源码总的来讲还是比较简单的,我们发现ScrollBy里面居然也是调用了ScrollTo呢,他们的区别就在于ScrollBy方法中调用ScrollTo时将传递的参数加上了当前 View内容View边缘位置的距离 (mScrollX、mScrollY)。

关于mScrollTo和mScrollBy这里我是这样理解的:

mScrollX    是View左边缘与View内容左边缘的水平方向上的距离,理解为View左边缘X坐标减去View内容左边缘X坐标。

mScrollY    是View顶部与View内容上边缘的在竖直方向上的距离,理解为View顶部Y坐标减去View内容顶部Y坐标。

我们用两幅图来表示:绿色部分为View的内容,框就是View本身。

这里大概能将mScrollX和mScrollY的取值表述清楚了。


下面用一个Demo演示一下ScrollTo和ScrollBy的区别:

Activity:

package com.example.xuzhenhao.myapplication.ui;import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;import com.example.xuzhenhao.myapplication.R;public class TestActivity extends AppCompatActivity {private RelativeLayout rl;private TextView tvTo;private TextView tvBy;private int x = -5;private int y = -5;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_test);initView();}/*** 初始化控件*/private void initView() {rl = (RelativeLayout) findViewById(R.id.scroll_rl);tvTo = (TextView) findViewById(R.id.scroll_tv);tvTo.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {int action = event.getAction();switch (action){case MotionEvent.ACTION_DOWN:rl.scrollTo(x,y);break;case MotionEvent.ACTION_MOVE:break;case MotionEvent.ACTION_UP:break;}return false;}});tvBy = (TextView) findViewById(R.id.scroll_by_tv);tvBy.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {int action = event.getAction();switch (action){case MotionEvent.ACTION_DOWN:rl.scrollBy(x,y);break;case MotionEvent.ACTION_MOVE:break;case MotionEvent.ACTION_UP:break;}return false;}});}
}

XML:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/scroll_rl"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context="com.example.xuzhenhao.myapplication.ui.TestActivity"><TextViewandroid:id="@+id/scroll_to_tv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="@color/dark"android:textSize="16sp"android:text="ScrollTo"/><TextViewandroid:id="@+id/scroll_by_tv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@+id/scroll_to_tv"android:textColor="@color/dark"android:textSize="16sp"android:text="ScrollBy"/></RelativeLayout>

运行起来如下图所示:

我们发现ScrollTo只能移动一次,再次点击就不能移动了,而点击ScrollBy每次都能移动,玄机在哪里??刚刚放出的源码里面已经写的很清楚了。


ScrollTo第一次传参时将传入的形参分别赋值给mScrollX和mScrollY,而每次都会去判断mScrollX和mScrollY与传入的形参是否相等,如果相等就不会去移动。


ScrollBy方法内部调用ScrollTo,在调用ScrollTo时传入的参数为当前View内容的左边缘和顶部到View的左边缘和顶部的距离加上传入的形参,就相当于每次都实现了基于当前位置的相对滑动

注意:

ScroolTo和ScrollBy都只能移动View的内容,View本身是不会移动的,上图中两个View之所以跑了是因为我们是使用最外层布局RelativeLayout的ScrollTo和ScrollBy


感谢!

在此任玉刚的《Android开发艺术探索》第3章第二节View的滑动


这篇关于View的滑动之ScrollTo和ScrollBy的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/706375

相关文章

基于Redis有序集合实现滑动窗口限流的步骤

《基于Redis有序集合实现滑动窗口限流的步骤》滑动窗口算法是一种基于时间窗口的限流算法,通过动态地滑动窗口,可以动态调整限流的速率,Redis有序集合可以用来实现滑动窗口限流,本文介绍基于Redis... 滑动窗口算法是一种基于时间窗口的限流算法,它将时间划分为若干个固定大小的窗口,每个窗口内记录了该时间

MVC(Model-View-Controller)和MVVM(Model-View-ViewModel)

1、MVC MVC(Model-View-Controller) 是一种常用的架构模式,用于分离应用程序的逻辑、数据和展示。它通过三个核心组件(模型、视图和控制器)将应用程序的业务逻辑与用户界面隔离,促进代码的可维护性、可扩展性和模块化。在 MVC 模式中,各组件可以与多种设计模式结合使用,以增强灵活性和可维护性。以下是 MVC 各组件与常见设计模式的关系和作用: 1. Model(模型)

专题二_滑动窗口_算法专题详细总结

目录 滑动窗口,引入: 滑动窗口,本质:就是同向双指针; 1.⻓度最⼩的⼦数组(medium) 1.解析:给我们一个数组nums,要我们找出最小子数组的和==target,首先想到的就是暴力解法 1)暴力: 2)优化,滑动窗口: 1.进窗口 2.出窗口 3.更新值 2.⽆重复字符的最⻓⼦串(medium) 1)仍然是暴力解法: 2)优化: 进窗口:hash[s[rig

MFC中App,Doc,MainFrame,View各指针的互相获取

纸上得来终觉浅,为了熟悉获取方法,我建了个SDI。 首先说明这四个类的执行顺序是App->Doc->Main->View 另外添加CDialog类获得各个指针的方法。 多文档的获取有点小区别,有时间也总结一下。 //  App void CSDIApp::OnApp() {      //  App      //  Doc     CDocument *pD

Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.B

一个bug日志 FATAL EXCEPTION: main03-25 14:24:07.724: E/AndroidRuntime(4135): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.syyx.jingubang.ky/com.anguotech.android.activity.Init

hot100刷题第1-9题,三个专题哈希,双指针,滑动窗口

求满足条件的子数组,一般是前缀和、滑动窗口,经常结合哈希表; 区间操作元素,一般是前缀和、差分数组 数组有序,更大概率会用到二分搜索 目前已经掌握一些基本套路,重零刷起leetcode hot 100, 套路题按套路来,非套路题适当参考gpt解法。 一、梦开始的地方, 两数之和 class Solution:#注意要返回的是数组下标def twoSum(self, nums: Lis

自定义view中常用到哪些方法作用分别是什么

目录 构造函数onMeasure(int widthMeasureSpec, int heightMeasureSpec)onDraw(Canvas canvas)onLayout(boolean changed, int left, int top, int right, int bottom)onTouchEvent(MotionEvent event)onSizeChanged(int

【leetcode详解】考试的最大困扰度(滑动窗口典例)

实战总结: sum += answerKey[right] == c; 经典操作,将判断语句转化为0, 1接收来计数//大问题分解: 对'T'还是'F'做修改, 传参为c//滑动窗口: 遍历, 维护left& right指向 及 c的个数, 更新不知从何下手写代码时:考虑先写好第一次的,然后以此为基础补充代码以适后续情况 题面: 解题感受: 思路总体好想, 实现略有挑战。 思路分析:

【每日一题】LeetCode 2379.得到K个黑块的最少涂色次数(字符串、滑动窗口)

【每日一题】LeetCode 2379.得到K个黑块的最少涂色次数(字符串、滑动窗口) 题目描述 给定一个字符串 blocks,其中每个字符代表一个颜色块,可以是 ‘W’(白色)或 ‘B’(黑色)。你需要找到一个至少包含 k 个连续黑色块的子串。每次操作可以将一个白色块变成黑色块。你的任务是找到至少出现一次连续 k 个黑色块的最少操作次数。 和该题目类似:【每日一题】LeetCode 202

【视频教程】手把手AppWizard轻松制作一个emWin滑动主界面控制框架,任意跳转控制(2024-09-06)

现在的新版AppWizard已经比较好用,用户可以轻松的创建各种项目常规界面。 比如早期创建一个支持滑动的主界面框架,并且可以跳转各种子界面,仅仅界面布局和各种图片格式转换都要花不少时间,而现在使用AppWizard,可以说轻轻松松,毫不费力。 用户唯一要做的就是根据自己的芯片性能做一定的速度优化。 视频: https://www.bilibili.com/video/BV17Rp3eLE