Android View 的滑动

一、View 的简介

View是所有可视化控件的基类,我们平时接触的所有的控件,比如说TextView,Button 等等都继承于View。View是Android 在视觉上的呈现,是界面层控件的一种抽象,可以是单个控件也可以是一组控件。

二、坐标系

1、Android 坐标系

在Android中,屏幕的左上角定点被视为Android坐标系的原点,原点向右是X轴正方向,原点向下是Y轴正方向。在触控事件中使用 getRawX()getRawY() 来获取Android 坐标系的坐标,也可以称之为绝对坐标
Android 坐标系

2、视图(View)坐标系

视图坐标系是用来描述当前View 和父视图的位置关系的。这里是以父视图的左上角定点为视图坐标系的原点,原点向右是X轴正方向,原点向下是Y轴正方向。在触控事件中使用getX()getY() 来获取视图坐标系的坐标,也可以称之为相对坐标.
视图(View)坐标系

三、View滑动的实现

View 的滑动实现逻辑:当触摸事件传到View 时,记录下触摸点的坐标,手指在移动的时候记下移动后的触摸坐标并算出偏移量,然后通过偏移量来修改View 的坐标。

MotionEvent

我们要实现View的滑动要在 onTouchEvent(MotionEvent event)中进行触摸事件的监听,MotionEvent 是触控事件的封装,简短的介绍下MotionEvent中封装的事件常量:

public static final int ACTION_DOWN = 0; //单点触摸按下动作
public static final int ACTION_UP = 1; //单点触摸离开动作
public static final int ACTION_MOVE = 2; //单点触摸移动动作
public static final int ACTION_CANCEL = 3; //触摸动作取消
public staiic final int ACTION_OUTSIDE = 4; //触摸动作超出边界
public static final int ACTION_POINTER_DOWN = 5; //多点触摸按下动作
public static final int ACTION_POINTER_UP = 6; 多点离开动作

1、layout()方法

view进行绘制的时候会调用onLayout()方法来设置显示的位置,因此我们同样也可以通过修改View的left、top、right、bottom这四种属性来控制View的坐标:

@Overridepublic boolean onTouchEvent(MotionEvent event) {// 获取触摸点的x,yint x = (int) event.getX();int y = (int) event.getY();switch (event.getAction()) {case MotionEvent.ACTION_DOWN:// 记录触摸点坐标lastX = x;lastY = y;break;case MotionEvent.ACTION_MOVE:// 计算偏移量int moveX = x - lastX;int moveY = y - lastY;//  更改位置layout(getLeft() + moveX, getTop() + moveY,getRight() + moveX, getBottom() + moveY);break;}return true;}

2、offsetLeftAndRight()和offsetTopAndBottom

传入偏移量后,这两个方法就是对View左右、上下移动的操作。

@Overridepublic boolean onTouchEvent(MotionEvent event) {// 获取触摸点的x,yint x = (int) event.getX();int y = (int) event.getY();switch (event.getAction()) {case MotionEvent.ACTION_DOWN:// 记录触摸点坐标lastX = x;lastY = y;break;case MotionEvent.ACTION_MOVE:// 计算偏移量int moveX = x - lastX;int moveY = y - lastY;//  更改位置offsetLeftAndRight(moveX);offsetTopAndBottom(moveY);break;}return true;}

3、LayoutParams

LayoutParams保存了View的布局参数,所以我们可以改变LayoutParams来动态的改变布局的位置来达到滑动的效果。

@Overridepublic boolean onTouchEvent(MotionEvent event) {// 获取触摸点的x,yint x = (int) event.getX();int y = (int) event.getY();switch (event.getAction()) {case MotionEvent.ACTION_DOWN:// 记录触摸点坐标lastX = x;lastY = y;break;case MotionEvent.ACTION_MOVE:// 计算偏移量int moveX = x - lastX;int moveY = y - lastY;//  更改位置LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) getLayoutParams();params.leftMargin = getLeft() + moveX;params.topMargin = getTop() + moveY;setLayoutParams(params);break;}return true;}

其实LayoutParams 完全可以配合 xml 中的layout_widthlayout_marginLeft 等等这些前面带layout_ 的属性去理解,设置LayoutParams 各个参数的过程就是动态设置xml中带layout_ 各个属性的过程。关于LayoutParams 的详细分析,可以参照这位大神写的博客 自定义控件知识储备-LayoutParams的那些事,写的很透彻,完全被圈粉。

4、ScrollTo 和 scrollBy

scollTo(x,y)表示移动到一个具体的坐标点,而scollBy(dx,dy)则表示移动的增量为dx、dy。查看scollBy()源码最终也是要调用scollTo的,举个例子说明下scollBy()是怎样移动的:
这里写图片描述
这里写图片描述

我们都知道画布的大小是无限大的,而坐标系是基于屏幕的左上角为原点的,所以屏幕中的控件的Android 坐标是(40,50),当我们执行scrollBy(30,30) 的时候,按照字面意思,这个控件的位置应该会出现在当前红色屏幕的右下方,可是事实上却出现在了屏幕的左上方。这是因为当执行scrollBy()方法的时候,我们的屏幕会沿着X轴正方向平移30,向Y轴正方向平移30,也就是屏幕向右下方平移了,此时红色的位置就是当前屏幕的位置。当执行完ScrollBy 以后,坐标系就会继续基于屏幕的左上角为原点,所以此时的屏幕中的控件的Android坐标为(10,20)。所以当我们调用scrollBy 方法的时候,要设置值为负数才能得到自己想要的移动效果。
scollTo、scollBy移动的是View的内容,如果在ViewGroup中使用则是移动他所有的子View,这点要特别注意。

@Overridepublic boolean onTouchEvent(MotionEvent event) {// 获取触摸点的x,yint x = (int) event.getX();int y = (int) event.getY();switch (event.getAction()) {case MotionEvent.ACTION_DOWN:// 记录触摸点坐标lastX = x;lastY = y;break;case MotionEvent.ACTION_MOVE:// 计算偏移量int moveX = x - lastX;int moveY = y - lastY;//  更改位置((View) getParent()).scrollBy(-moveX, -moveY);break;}return true;}

5、Scroller

我们用scollTo/scollBy方法来进行滑动时,这个过程是瞬间完成的,所以用户体验不大好。这里我们可以使用Scroller来实现有过度效果的滑动,这个过程不是瞬间完成的,而是在一定的时间间隔完成的。Scroller本身是不能实现View的滑动的,它需要配合View的computeScroll()方法才能弹性滑动的效果。Scroller的基本用法其实还是比较简单的,主要可以分为以下几个步骤:
1. 创建Scroller的实例
2. 调用startScroll()方法来初始化滚动数据并刷新界面
3. 重写computeScroll()方法,并在其内部完成平滑滚动的逻辑

public class ScrollerView extends View {private Scroller mScroller;public ScrollerView(Context context) {super(context);}public ScrollerView(Context context, AttributeSet attrs) {super(context, attrs);// 初始化ScrollermScroller = new Scroller(context);}public ScrollerView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}/*** 系统会在绘制View的时候在draw()方法中调用该方法,这个方法中我们调用父类的scrollTo()方法并通过Scroller* 来不断获取当前的滚动值,每滑动一小段距离我们就调用invalidate()方法不断的进行重绘,重绘就会调用* computeScroll()方法,这样我们就通过不断的移动一个小的距离并连贯起来就实现了平滑移动的效果*/@Overridepublic void computeScroll() {super.computeScroll();if (mScroller.computeScrollOffset()) {((View) getParent()).scrollTo(mScroller.getCurrX(), mScroller.getCurrY());//通过不断的重绘不断的调用computeScroll方法invalidate();}}/*** 提供2秒内平滑的滑动方法* @param destX* @param destY*/public void smoothScrollTo(int destX, int destY) {int scrollX = getScrollX();int scrollY = getScrollY();int deltaX = destX - scrollX;int deltaY = destY - scrollY;// 在2秒内滑到destX destYmScroller.startScroll(scrollX, scrollY, deltaX, deltaY, 2000);invalidate();}
}

结尾:以上就是关于View 滑动的相关内容了,当然还有属性动画也能控制View 的滑动,我准备放到动画篇讲解。下面附上源码:https://github.com/smile-sxl/CustomView

转载于:https://www.cnblogs.com/javasxl/p/9397774.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/368482.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

flask 检测post是否为空_使用Flask搭建一个校园论坛-4

在上一节中完成了注册功能的前期准备工作,在这一节内容中将完成用户注册、登录功能。1.知识预览在本届中将学习到以下内容的知识如何使用wtform来渲染表单如果使用flask-mail来发送邮件2.用户注册在前端中form表单是用的比较多的东西,我们可以使用wtform…

SQL Table 自动生成Net底层-生成数据操作Repository

生成接口类 public static string DataTableToBaseIService(string tableName, string nameSpace, string className){var table SqlTableHelper.GetSQLTableInfo(tableName);StringBuilder reval new StringBuilder();reval.AppendFormat(" using System; using…

自定义Spring命名空间使JAXB更容易

首先,让我大声说出来: Spring不再是XML繁重的了 。 事实上,如今,您可以使用大量注释, Java配置和Spring Boot来编写几乎没有XML或根本没有XML的Spring应用程序。 认真地停止谈论Spring和XML,这已经成为过去…

利用锚点再点事吧丨

上图 接着HTML代码&#xff1a; <div id"color"> <div id"red">红</div> <div id"yellow">黄</div> <div id"black">黑</div> <div id"green">绿</div> </div>…

javaweb笔记1

转载于:https://www.cnblogs.com/webdev8888/p/9164291.html

以太网数据帧的报尾封装字段是什么_16、90秒快速“读懂”数据包的封装、解封装...

数据转发过程概述数据包在相同网段内或不同网段之间转发所依据的原理基本一致。一、数据帧封装TCP封装(四层)当主机建立了到达目的地的TCP连接后&#xff0c;便开始对应用层数据进行封装。主机A会对待发送的应用数据首先执行加密和压缩等相关操作&#xff0c;之后进行传输层封装…

CSS基本知识(慕课网)

1、注释 注解&#xff1a;CSS中注释/*这里是注释的文字*/ HTML中注释<!--这里是注释的文字--> 2、外部式css样式&#xff0c;写在单独的一个文件中 注解&#xff1a; 外部式css样式(也可称为外联式)就是把css代码写一个单独的外部文件中&#xff0c;这个css样式文件以“…

JMS和Spring:有时很重要的小事情

JmsTemplate和DefaultMessageListenerContainer是用于访问JMS兼容MOM的Spring帮助器。 他们的主要目标是在JMS API之上形成一层&#xff0c;并处理诸如事务管理/消息确认之类的基础结构&#xff0c;并隐藏JMS API的某些重复和笨拙的部分&#xff08;保留在那里&#xff1a; JMS…

css实现3D立方体旋转特效

先来看运行后出来的效果 它是在不停运行的一个立方体 先来看html部分的代码 <div class"rect-wrap"> <!--舞台元素&#xff0c;设置perspective&#xff0c;让其子元素获得透视效果。--><div class"container"> <!-- 容器&#…

Eclipse中的Tomcat:6个流行的“如何”问题

学习新技术总是一个艰难的过程。 当您尝试学习将要相互交互的两种技术时&#xff0c;此过程将变得更加困难。 Tomcat和Eclipse是Java EE开发中最流行的先决条件。 因此&#xff0c;要成为一名专业的开发人员&#xff0c;您需要知道如何使用此对执行最需要的操作以及如何进行一些…

adc分辨率和精度的区别_科普 | 传感器的灵敏度、分辨率和精度三者之间有何区别?...

传感器作为一种检测装置&#xff0c;具有微型化、数字化、智能化、多功能化、系统化、网络化的特点。在现代工业生产尤其是自动化生产过程中&#xff0c;需要各种传感器来监视和控制生产过程中的各个参数&#xff0c;使设备工作在正常状态或最佳状态&#xff0c;并使产品达到最…

Linux上的HotSpot GC线程CPU占用空间

以下问题将测试您对Linux操作系统上运行的Java应用程序的垃圾回收和高CPU故障排除的知识。 当调查过多的GC和/或CPU利用率时&#xff0c;此故障排除技术尤其重要。 它将假定您没有访问高级监视工具的能力&#xff0c;例如Compuware dynaTrace甚至JVisualVM。 将来会介绍使用此类…

tornado-简介和原理

tornado-设计初衷 1. 追求小而精 2. epoll IO多路复用和协程 3. 支持WebSocket 4. 单线程程序(GIL限制&#xff0c;本身某种意义上不启动多进程就是单线程程序) # Python GIL介绍详情 tronado应用场景 1. 大量的http请求连接(大量的用户请求&#xff0c;要求并发性和高性能) tr…

前端学习笔记--HTTP缓存

原文地址&#xff1a;https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hlzh-cn 缓存并重用之前获取的资源的能力是性能优化的一个关键方面。 每个浏览器都自带了 HTTP 缓存实现功能&#xff0c;只需要确保每个服务…

如何用Veripacks替换构建模块

比较下面的两棵树。 在这两种情况下&#xff0c;目标都是拥有一个具有两个独立模块&#xff08; frontend和reporting &#xff09;和一个共享/公用模块&#xff08; domain &#xff09;的应用程序。 frontend的代码不应访问reporting代码&#xff0c;反之亦然。 两个模块都可…

JS的DOM和BOM

* JavaScript分三个部分: ECMAScript标准:JS的基本的语法DOM:Document Object Model --->文档对象模型----操作页面的元素BOM:Browser Object Model----->浏览器对象模型---操作的是浏览器一、DOM对象 文档:把一个html文件看成是一个文档,由于万物皆对象,所以把这个文档看…

数据库(11)-- Hash索引和BTree索引 的区别

索引是帮助mysql获取数据的数据结构。最常见的索引是Btree索引和Hash索引。 不同的引擎对于索引有不同的支持&#xff1a;Innodb和MyISAM默认的索引是Btree索引&#xff1b;而Mermory默认的索引是Hash索引。 Hash索引 哈希索引包含以数组形式组织的 Bucket 集合。 哈希函数将索…

MySQL的复制:MySQL系列之十三

一、MySQL复制相关概念 主从复制&#xff1a;主节点将数据同步到多个从节点级联复制&#xff1a;主节点将数据同步到一个从节点&#xff0c;其他的从节点在向从节点复制数据同步复制&#xff1a;将数据从主节点全部同步到从节点时才返回给用户的复制策略叫同步复制异步复制&…

将NetBeans代码模板弯曲到我的意愿

任何阅读过我关于NetBeans的文章的人都知道&#xff0c;我真的很喜欢NetBeans的众多功能。 但是&#xff0c;最近&#xff0c;我发现自己对NetBeans特定功能的特定问题越来越恼火。 最终&#xff0c;它使我烦恼不已&#xff0c;促使我开始研究如何根据自己的喜好禁用或更改该功…

MySQL安装过程

最近试着重装了下MySQL&#xff0c;安装过程很简单&#xff0c;希望能帮助大家 mysql安装过程 1. 下载&#xff1a; 我下载的是64位系统的zip包&#xff1a; 下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/ 下载zip的包。 下载后解压到对应目录 如&#xff1a;D:…