1.View的滑动简介

View的滑动是Android实现自定义控件的基础,同时在开发中我们也难免会遇到View的滑动的处理。其实不管是那种滑动的方式基本思想都是类似的:当触摸事件传到View时,系统记下触摸点的坐标,手指移动时系统记下移动后的触摸的坐标并算出偏移量,并通过偏移量来修改View的坐标。 
实现View滑动有很多种方法,这篇文章主要讲解六种滑动的方法,分别是:layout()、offsetLeftAndRight()与offsetTopAndBottom()、LayoutParams、动画、scollTo与scollBy和Scroller;在下一篇文章我们会详细介绍属性动画。

2.实现View滑动的六种方法

1.layout()

view进行绘制的时候会调用onLayout()方法来设置显示的位置,因此我们同样也可以通过修改View的left、top、right、bottom这四种属性来控制View的坐标。首先我们要自定义一个View,在onTouchEvent()方法中获取触摸点的坐标:

public boolean onTouchEvent(MotionEvent event) {//获取到手指处的横坐标和纵坐标
    int X = 0, newX = 0;
    int Y = 0, newY = 0;
    switch (event.getAction()) {case MotionEvent.ACTION_DOWN:Log.d("hahahhaha", "屏幕位置被按下");
            X = (int) event.getX();
            Y = (int) event.getY();

            break;

接下来我们在ACTION_MOVE事件中计算偏移量,再调用layout()方法重新放置这个自定义View的位置就好了:

public boolean onTouchEvent(MotionEvent event) {//获取到手指处的横坐标和纵坐标
    int X = 0, newX = 0;
    int Y = 0, newY = 0;
    switch (event.getAction()) {case MotionEvent.ACTION_DOWN:Log.d("hahahhaha", "屏幕位置被按下");
            X = (int) event.getX();
            Y = (int) event.getY();

            break;
        case MotionEvent.ACTION_MOVE:Log.d("hahahhaha", "屏幕位置在移動");
            newX = (int) event.getX();
            newY = (int) event.getY();

            int offsetX = newX - X;
            int offsetY = newY - Y;
            Log.d("hahaha", "offsetX=" + offsetX + ",offsetY=" + offsetY);
            //1.调用layout方法来重新放置它的位置
            layout(getLeft()+offsetX, getTop()+offsetY,
                    getRight()+offsetX , getBottom()+offsetY);

当我们每次移动时都会调用layout()方法来对自己重新布局,从而达到移动View的效果。

2.offsetLeftAndRight()与offsetTopAndBottom()

这两种方法和layout()方法效果方法差不多,使用也差不多,我们将ACTION_MOVE中的代码替换成如下代码:

            case MotionEvent.ACTION_MOVE://计算移动的距离int offsetX = x - lastX;int offsetY = y - lastY;//对left和right进行偏移offsetLeftAndRight(offsetX);//对top和bottom进行偏移offsetTopAndBottom(offsetY);break;

3.LayoutParams(改变布局参数)

LayoutParams主要保存了一个View的布局参数,因此我们可以通过LayoutParams来改变View的布局的参数从而达到了改变View的位置的效果。同样的我们将ACTION_MOVE中的代码替换成如下代码:

  LinearLayout.LayoutParams layoutParams= (LinearLayout.LayoutParams) getLayoutParams();layoutParams.leftMargin = getLeft() + offsetX;layoutParams.topMargin = getTop() + offsetY;setLayoutParams(layoutParams);
  • 1
  • 2
  • 3
  • 4

因为父控件是LinearLayout,所以我们用了LinearLayout.LayoutParams,如果父控件是RelativeLayout则要使用RelativeLayout.LayoutParams。除了使用布局的LayoutParams外,我们还可以用ViewGroup.MarginLayoutParams来实现:

                ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams();layoutParams.leftMargin = getLeft() + offsetX;layoutParams.topMargin = getTop() + offsetY;setLayoutParams(layoutParams);

4.scollTo与scollBy

scollTo(x,y)表示移动到一个具体的坐标点,而scollBy(dx,dy)则表示移动的增量为dx、dy。其中scollBy最终也是要调用scollTo的。scollTo、scollBy移动的是View的内容,如果在ViewGroup中使用则是移动他所有的子View。我们将ACTION_MOVE中的代码替换成如下代码:

 ((View)getParent()).scrollBy(-offsetX,-offsetY);
  • 1
  • 1

这里要实现CustomView随着我们手指移动的效果的话,我们就需要将偏移量设置为负值。

5.Scroller

我们用scollTo/scollBy方法来进行滑动时,这个过程是瞬间完成的,所以用户体验不大好。这里我们可以使用Scroller来实现有过度效果的滑动,这个过程不是瞬间完成的,而是在一定的时间间隔完成的。Scroller本身是不能实现View的滑动的,它需要配合View的computeScroll()方法才能弹性滑动的效果。 
在这里我们实现CustomView平滑的向右移动。

  • 首先我们要初始化Scroller:
  public CustomView(Context context, AttributeSet attrs) {super(context, attrs);mScroller = new Scroller(context);}
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
  • 接下来重写computeScroll()方法,系统会在绘制View的时候在draw()方法中调用该方法,这个方法中我们调用父类的scrollTo()方法并通过Scroller来不断获取当前的滚动值,每滑动一小段距离我们就调用invalidate()方法不断的进行重绘,重绘就会调用computeScroll()方法,这样我们就通过不断的移动一个小的距离并连贯起来就实现了平滑移动的效果:
    @Overridepublic void computeScroll() {super.computeScroll();if(mScroller.computeScrollOffset()){((View) getParent()).scrollTo(mScroller.getCurrX(),mScroller.getCurrY());//通过不断的重绘不断的调用computeScroll方法invalidate();}  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 调用Scroller.startScroll()方法。我们在CustomView中写一个smoothScrollTo()方法,调用Scroller.startScroll()方法,在2000毫秒内沿X轴平移delta像素:
  public void smoothScrollTo(int destX,int destY){int scrollX=getScrollX();int delta=destX-scrollX;//1000秒内滑向destXmScroller.startScroll(scrollX,0,delta,0,2000);invalidate();}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 最后我们在ViewSlideActivity.java中调用CustomView的smoothScrollTo()方法:
          //使用Scroll来进行平滑移动mCustomView.smoothScrollTo(-400,0);
  • 1
  • 2
  • 1
  • 2

这里我们是设定CustomView沿着X轴向右平移400像素。

6.动画

可以采用View动画来移动,在res目录新建anim文件夹并创建translate.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"><translate android:fromXDelta="0" android:toXDelta="300" android:duration="1000"/>
</set>
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

在Java代码中引用:

  mCustomView.setAnimation(AnimationUtils.loadAnimation(this, R.anim.translate));
  • 1
  • 1

当然使用属性动画移动那就更简单了,我们让CustomView在1000毫秒内沿着X轴像右平移300像素:

ObjectAnimator.ofFloat(mCustomView,"translationX",0,300).setDuration(1000).start();

Android-实现View滑动的6种方式相关推荐

  1. android asynctask源码分析,Android通过Handler与AsyncTask两种方式动态更新ListView(附源码)...

    本文实例讲述了Android通过Handler与AsyncTask两种方式动态更新ListView的方法.分享给大家供大家参考,具体如下: 有时候我们需要修改已经生成的列表,添加或者修改数据,noti ...

  2. android打开另外的app两种方式,内置到自己本身的app,重新打开app,

    android打开另外的app两种方式,内置到自己本身的app空间,重新打开app空间, 目录 1.内置到自己本身的app空间, 2.重新打开app空间, 1.内置到自己本身的app空间, 被打开的a ...

  3. Android页面数据传递的两种方式

    在android中实现页面中数据的传递有两种方式: 1:第一种数据传递的方式是通过inputExtra方法来进行数据的传递的 2:第二中方法是通过bundle的方法来实现数据的传递的 接下来我们首先来 ...

  4. android四种点击事件,android点击事件的四种方式

    android点击事件的四种方式 第一种方式:创建内部类实现点击事件 代码如下: package com.example.dail; import android.text.TextUtils; im ...

  5. android xpath解析xml,Android 中处理 XML 的四种方式-DOM

    Android 中处理 XML 的几种方式连载中,我们就不介绍合成 XML 了,因为合成 XML 可以直接拼接字符串,虽然看起很不高大上,但却很有效.我们主要介绍如何取 XML 中的值. 适用 DOM ...

  6. Android点击图片随机,android 设置图片随机出现-两种方式

    android 设置图片随机出现-两种方式, 第一种方式:得到图片对应的Drawable实例,通过setImageDrawable(drawable)实现 //ImageView对应的id ivBg ...

  7. Android中播放音乐的几种方式

    Android中播放音乐的几种方式 前言 前几天一直在研究RxJava2,也写了记录了几篇博客,但因为工作任务原因,需要研究音频相关的知识,暂时放下Rxjava,本文的demo中,MediaPalye ...

  8. 【Android】播放音频的几种方式介绍

    转自:u013366008的博客  https://blog.csdn.net/u013366008/article/details/76577372 Android中播放音乐的几种方式 前言 前几天 ...

  9. android 设置图片随机出现-两种方式

    android 设置图片随机出现-两种方式, 第一种方式:得到图片对应的Drawable实例,通过setImageDrawable(drawable)实现 //ImageView对应的idivBg = ...

最新文章

  1. 程序员娶妻子的经典准则
  2. Android应用--简、美音乐播放器获取专辑图片(自定义列表适配器)
  3. 怎么查看python是多少位_python+位数
  4. 使用ObjectInputStream和ObjectOutputStream注意问题
  5. 电机与拖动,直流他励电动机的特性测试实验报告,江南大学自动化
  6. code换取微信openid_JSamp;微信_微信授权
  7. libevent book——event | Gaccob的博客
  8. 51单片机mysql_[学习笔记]15个QA让你快速入门51单片机开发
  9. python测试脚本实例-python脚本测试
  10. html打印多了空白页,为什么打印Word文档会多打印出一空白页
  11. wx.getLocation() 定位误差 解决
  12. Nvidia Jetson AGX Xavier 安装SATA接口固态硬盘
  13. Java实现excel 2003、2007导入功能
  14. Python find()方法
  15. 腾讯云星星海SA2云服务器优惠购买指南
  16. [附源码]Python计算机毕业设计SSM流浪动物救助及领养平台(程序+LW)
  17. 执行脚本,无故多出来两个进程号
  18. java中内部窗格这么用,JTabbedPane选项窗格的使用
  19. 树莓派TF卡低格,存储空间还原
  20. Filter过滤器的作用和工作原理

热门文章

  1. 通用Login功能自动化测试
  2. 【数据结构】顺序线性表的构造和存储数据
  3. Python进阶_wxpy学习:原始数据
  4. [云炬创业基础笔记]第七张创业资源测试
  5. [云炬创业基础笔记]第六章商业模式测试17
  6. 科大星云诗社动态20210425
  7. 科大星云诗社动态20210525
  8. 我用 PyTorch 复现了 LeNet-5 神经网络(CIFAR10 数据集篇)!
  9. D8016“/ZI”和“/Gy-”命令行选项不兼容问题的解决
  10. 串口通信模块1:串口基础知识