android群英传 自定义滑动view,Android群英传学习之路-View的滑动

滑动效果是如何产生的?

滑动一个View从本质上来说就是移动一个View,改变其当前的坐标。所以,想要滑动一个View,就必须监听该View的触摸事件,并且根据事件的坐标,不断的改变View的坐标从而实现View的滑动。

Android中的坐标体系

Android中的坐标体系分为两种:

Android坐标系

视图坐标系

Android坐标系

BeuoVGffvDpd72jM.jpg

Android坐标系

从图中我们可以看的出来**在Android坐标系中以屏幕的左上方作为坐标系的原点,从原点向右为X轴的正方向,向下为Y轴的正方向**。在触控事件中使用**getRawX()、getRawY()**来获得Android坐标系的坐标

视图坐标系

puR17miMYRJtL4KE.png

视图坐标系

视图坐标系主要描述的是该View和该View在父视图中的位置关系,和Android坐标系一样,也是以原点右方为X正方向,以原点下方为Y轴正方向,不过这里不是以屏幕的左上角为原点,而是**以父视图的左上角为原点**。在触控事件中使用**getX()、getY()**来获得视图坐标系的坐标

触控事件

在上一篇文章中我们使用到了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; 多点离开动作

通常情况下我们会在onTouchEvent(MotionEvent event)方法中通过event.getAction()来获取触控事件的类型。知道Android中的坐标系和触控事件之后我们就可以来实现View的滑动了

滑动实现

实现滑动有好多种方法,但是其思想都是一样的。当触摸到View时,记录当前触摸点的坐标,然后当手指移动时,获取到相对于前一个点的偏移量,这样我们就可以通过这个偏移量来进行修改View的坐标,这样不断的重复,就能实现View的滑动

举个例子

我们自定义一个View,让他来跟随我们手指的移动来移动,如图:

4nCHXGhBZgbwlLGh.gif

layout方法

我们知道在View进行绘制的时候会通过onLayout()方法来设置View的显示位置,这里我们通过修改View的left, top, right, bottom四个值来控制View的坐标

public boolean onTouchEvent(MotionEvent event) {

int 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 offsetX = x - lastX;

int offsetY = y - lastY;

//在当前位置基础加上偏移量

layout(

getLeft() + offsetX,

getTop() + offsetY,

getRight() + offsetX,

getBottom() + offsetY

);

break;

}

return true;

}

offsetLeftAndRight()和offsetTopAndBottom

这个方法就是相当于系统提供的一个对左右、上下移动的API的封装,计算好偏移量后,调用方法即可:

offsetLeftAndRight(offsetX);

offsetTopAndBottom(offsetY);

LayoutParams

LayoutParams保存了View的布局参数,所以我们可以改变LayoutParams来动态的改变布局的位置来达到滑动的效果。在程序中使用getLayoutParams()来获取当前View的LayoutParams,这里就和上面一样,获取到偏移量后通过setLayoutParams来设置该View的LayoutParams:

RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) getLayoutParams();

params.leftMargin = getLeft() + offsetX;

params.topMargin = getTop() + offsetY;

setLayoutParams(params);

需要注意一点,通过getLayoutParams()获取LayoutParams的时候,要根据View的父布局的类型来设置,当然前提还要有一个父布局。还有就是我们可以使用ViewGroup.MarginLayoutParams,这样就不用考虑父布局是什么了

scrollTo、scrollBy

在View中,系统还提供了scrollTo、scrollBy两种方式来改变一个View的位置。

其中scrollTo表示移动到一个具体的坐标点,scrollBy表示移动的偏移量,其实在scrollBy内部也是调用的scrollTo。

和前面的方式一样,获取到偏移量后调用scrollBy来移动view,可是当我们运行程序,拖动View,发现View并没有移动!这是因为scrollTo、scrollBy方法移动的是View的内容,如果在ViewGroup中使用scrollTo、scrollBy的滑,那么移动的就是View了,但是如果在View中使用,那么移动的将是View里面的内容,比如TextView,那么移动的就是文本了。

所以通过上面的分析,我们把代码改为如下:

((View)getParent()).scrollBy(offsetX, offsetY);

再次运行程序,我们会发现动是动了,但是在乱动。因为这里我们其实是在相反的方向移动(这里由于篇幅限制,感兴趣的同学自行查找一下资料),我们把偏移量改为负的之后就会发现滑动正常了。

Scroller

首先来想一个场景:我们需要让一个Button向右面移动100个像素,如果我们用scrollTo/scrollBy的话,那么该View就会很突兀的移动到该点,没有过程,而Scroller则是可以实现平滑的过渡效果的

下面我们把上面跟随手指滑动的例子改一下,我们在松开手指后,View自动回到原点(屏幕左上角)。使用Scroller需要三个步骤

初始化

通过构造方法即可 Scroller mScroller = new Scroller(context);

重写computeScroll()方法,实现滑动

startScroll()开启滑动

代码如下:

case MotionEvent.ACTION_UP:

View viewGroup = (View) getParent();

mScroller.startScroll(

viewGroup.getScrollX(),

viewGroup.getScrollY(),

-viewGroup.getScrollX(),

-viewGroup.getScrollY()

);

invalidate();

break;

----------------------------------------------------------------

@Overrid

public void computeScroll() {

super.computeScroll();

if (mScroller.computeScrollOffset()) {

((View) getParent()).scrollTo(mScroller.getCurrX(), mScroller.getCurrY());

invalidate();

}

}

当我们手指抬起来的时候开启Scroller滑动,获取到当前view的移动距离,然后我们把需要移动的偏移量设置为相反数就ok,最后调用invalidate来通知重绘,从而调用computeScroll()方法。运行程序如下:

zIn1P7eOLR4hzpD1.gif

现在就把这几种View的滑动都说完了,自己动手写一下,感触良多。

最后

爱生活,爱小丽,爱Android

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

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

相关文章

艹,正则表达式!

大家好,我是球哥,转发良许同学的一篇文章。不知道大家有没有被正则表达式支配过的恐惧?看着一行火星文一样的表达式,虽然每一个字符都认识,但放在一起直接就让人蒙圈了~你是不是也有这样的操作,比如你需要使…

双向循环链表的插入与删除

关于解释部分不再多说了,网上资料很多,下面就介绍具体的实现吧 //双向循环链表的插入与删除 typedef struct node{int data;struct node *prev, *next;}DNode, *DLinkList;//在带有头结点双向循环链表中第1个数据域内容为x的结点右边插入一个数据信息为i…

Linux Centos安装步骤

在虚拟机VMware10上安装Centos系统步骤 (1)首先需要创建一个虚拟机,选择操作系统,进行一系列的硬件配置,选择Centos系统镜像 虚拟机创建完成 虚拟机创建完成后,重新启动虚拟机,就会自动开始安装CentOS系统的…

关于EMF模型的操作,赶紧记下来

前几天问了一个同事EMF模型操作的问题,还没来的验证,先记下再说! 当在EditDomain下操作模型时,所有对模型的修改需要在Command中完成,并且涉及到了EMF事务处理。不在EditDomain下操作模型,不涉及事务&#…

android include 点击事件,Android编程之include文件的使用方法

本文实例分析了Android编程之include文件的使用方法。分享给大家供大家参考,具体如下:记得很久以前,听一位大神说,程序员都很懒,不懒惰的程序员不是好程序员,当时不明白什么意思.后来慢慢的懂得…

通信PK电子,谁牛?

工程师很多都有强迫症,有的是拆解强迫症,有的是排线布线强迫症,至今还记得第一堂焊电路板的课上,有同学把跳线排排焊,期末考获得了光荣的A。论起排线布线的手艺,早前,德国弱电工程师的完美布线让…

[机器视觉] SIFT特征-尺度不变特征理解

SIFT特征-尺度不变特征理解 简介 SIFT,即尺度不变特征变换(Scale-invariant feature transform,SIFT),是用于图像处理领域的一种描述。这种描述具有尺度不变性,可在图像中检测出关键点,是一种局…

公司应该如果管理员工?

昨天晚上我看了一个讲座,谈对公司管理员工的方法,其中有三点:1、人管人[中国普遍公司中存在];2、制度管人[大部分公司是这样];3、文化管人[极少数公司]也是公司管理员工的至高无尚的无境界!;仔细…

【转载】MongoDB基本操作

园子里已经有不少朋友发过MongoDB的帖子,但是都比较高端,我在这里就写下比较基础的应用,算是MongoDB的第一次接触有所了解。呵呵。我们去Mongodb.org看一看。首页赫然写着 The Best Features of Document Databases,Key-Value Stores,and RDB…

harmonyos手机开发者beta,HarmonyOS 手机应用开发者 Beta 版到来,对开发者意味着什么...

北京时间12月16日,HarmonyOS手机开发者Beta活动在北京国贸开启,这场活动现场的人潮涌动也足以说明一切——用户和开发者对HarmonyOS手机应用开发者Beta版期待已久。作者 | 贾凯强头图 | 华为官方提供打破手机单设备限制,为万物互联而生在活动…

你确定不反编译 likely 看看?

大家好,我是写代码的篮球球痴,下面推荐飞哥的一篇文章,觉得对大家很有帮助,希望大家先看看再扔到收藏夹吃灰,转发不转发看大爷们心情咯!今天我给大家分享一个内核中常用的提升性能的小技巧。理解了它对你一…

fwrite在任意位置写入文件,并可修改文件内容

想实现类似迅雷那样下载时可以从文件半中间写入的功能#include<stdio.h> int main() { FILE *fp; fpfopen("overwrite.bin","rb"); //使用rb模式,可以往半中间插入数据,而且是覆盖插入,若使用"ab"每次都插入到…

新网卡不能绑定“旧”IP故障的解决

问&#xff1a;有一台电脑&#xff0c;操作系统是Windows 原来装有一张RTL8139的PCI网卡&#xff0c;绑定IP地址为192.168.221.48&#xff0c;后来把这张网卡换了一个插槽&#xff0c;开机后系统却把它认为是张新网卡&#xff0c;再去绑定原来的那个IP地址&#xff0c;提示&quo…

看完这篇文章,会让你对电容的作用更明白!

电容是电路设计中最为普通常用的器件&#xff0c;是无源元件之一&#xff0c;有源器件简单地说就是需能(电)源的器件叫有源器件&#xff0c;无需能(电)源的器件就是无源器件。电容的作用和用途一般都有好多种&#xff0c;如&#xff1a;在旁路、去耦、滤波、储能方面的作用&…

查看及修改MYSQL最大连接数

查看Mysql连接数 登录到mysql客户端后&#xff0c;使用status命令也能获得thread连接数以及当前连接的id 或者用 Mysql代码 show full processlist 看一下所有连接进程&#xff0c;注意查看进程等待时间以及所处状态 是否locked 如果进程过多&#xff0c;就把进程打印下…

华为mate40pro 升级鸿蒙,华为Mate40Pro再次曝光,麒麟9000+可升级到鸿蒙OS,这才是华为...

原标题&#xff1a;华为Mate40Pro再次曝光&#xff0c;麒麟9000可升级到鸿蒙OS&#xff0c;这才是华为在如今的手机市场&#xff0c;创新和差异化的设计已经成为消费者最在意的地方&#xff0c;所以加大技术创新和研发投入才是手机厂商们谋求发展的唯一道路。华为手机是一个大家…

uva 133解题报告

题目描述 为了缩短领救济品的队伍&#xff0c;NNGLRP决定了以下策略&#xff1a;每天所有来申请救济品的人会被放在一个大圆圈&#xff0c;面朝里面。选定一个人为编号 1 号&#xff0c;其他的就从那个人开始逆时针开始编号直到 N。一个官员一开始逆时针数&#xff0c;数 k 个申…

fopen与读写的标识r,r+,rb+,rt+,w+.....

函数简介 函数功能&#xff1a; 打开一个文件 函数原型&#xff1a;FILE * fopen(const char * path,const char * mode); 相关函数&#xff1a;open&#xff0c;fclose&#xff0c;fopen_s[1]&#xfeff; &#xff0c;_wfopen 所需库&#xff1a; <stdio.h> 返回值&…

WPF(Windows Presentation Foundation)Overview

在Windows NT中&#xff0c;图形多媒体系统基于层次结构。应用程序与顶层的API&#xff08;实际上是多个用户模式的系统DLL&#xff0c;比如GDI32.DLL&#xff09;交互&#xff0c;这些系统DLL最终会通过系统服务调用处于内核模式的系统服务。NT系统的详细信息可参考《Windows …

10年深圳,回去了

十年前&#xff0c;2012年&#xff0c;我们毕业。毕业后&#xff0c;我们很多人都选择来深圳&#xff0c;那时候的想法很简单&#xff0c;深圳有我们想要的工作&#xff0c;我们很多人都是村里来的孩子&#xff0c;没有背景&#xff0c;家里也没有矿。考不上公务员也不想去做老…