View滑动的基本思想:当点击事件传到View时,系统记下触摸点的坐标,手指移动时系统记下触摸后的坐标并计算出偏移量,然后根据偏移量修正View坐标.

实现View滑动共有6种方法:layout()方法,offsetTopAndBottom(),LayoutParams,动画,scrollTo与scrollBy,以及Scroller.

一.layout()

  1. import ...;
  2.  
  3. public class CustomView extends View {
  4. private int lastX;
  5. private int lastY;
  6.  
  7. public CustomView(Context context) {
  8. super(context);
  9. }
  10.  
  11. public CustomView(Context context, AttributeSet attrs) {
  12. super(context, attrs);
  13. }
  14.  
  15. public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
  16. super(context, attrs, defStyleAttr);
  17. }
  18.  
  19. public CustomView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
  20. super(context, attrs, defStyleAttr, defStyleRes);
  21. }
  22.  
  23. @Override
  24. public boolean onTouchEvent(MotionEvent event) {
  25. int x = (int) event.getX();
  26. int y = (int) event.getY();
  27.  
  28. switch (event.getAction()) {
  29. case MotionEvent.ACTION_DOWN:
            //获取手指按下时,触摸点位置
  30. lastX = x;
  31. lastY = y;
  32. break;
  33. case MotionEvent.ACTION_MOVE:
            //获取移动后触摸点位置,计算偏移量
  34. int offsetX = x - lastX;
  35. int offsetY = y - lastY;
            //修改View的left,top,right,bottom属性重新放置View
  36. layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);
  37. break;
  38. }
  39. return true;
  40. }
  41. }

然后在布局文件中引用就好了:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. tools:context=".MainActivity"
  8. android:orientation="vertical"
  9. >
  10.  
  11. <com.example.scroll_test.CustomView
  12. android:layout_width="80dp"
  13. android:layout_height="80dp"
  14. android:background="@color/colorAccent"
  15. />
  16.  
  17. </LinearLayout>

二.offsetLeftandRight

这种方法与Layout()方法相似,只需将ACTION_MOVE修改成以下代码:

  1. case MotionEvent.ACTION_MOVE:
  2. int offsetX = x - lastX;
  3. int offsetY = y - lastY;
  4. offsetLeftAndRight(offsetX);
  5. offsetTopAndBottom(offsetY);
  6. break;
  7. }

三.LayoutParams(改变布局参数)

通过LayoutParams改变View的布局参数,从而达到修改View位置的效果.

将ACTION_MOVE修改成以下代码:

  1. case MotionEvent.ACTION_MOVE:
  2. int offsetX = x - lastX;
  3. int offsetY = y - lastY;
              
  4. LinearLayout.LayoutParams layoutParams= (LinearLayout.LayoutParams) getLayoutParams();
  5. layoutParams.leftMargin=getLeft() + offsetX;
  6. layoutParams.topMargin=getTop() + offsetY;
  7. setLayoutParams(layoutParams);
  8. break;
  9. }

由于父控件是LinearLayout,所以用到了LineatLayout.LayoutParams.如果是RelativeLayout,则要使用RelativeLayot.LayoutParams.还可以用ViewGroup.MarginLayoutParams来实现:

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

四.属性动画

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

五.scrollTo与scrollBy

scrollTo(x,y)表示移动到一个具体的点,scrollBy(dx,dy)表示移动的增量为dx,dy.

scrollTo,scrollBy移动的是View的内容,如果在ViewGround中使用,则是移动其所有的子View..我们将ACTION_MOVE替换成如下代码:

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

设置为负值,则CustomView会跟随手滑动.原因是因为此时移动的是手机屏幕,布局是不移动的.布局中的控件也是不懂的,手指向右滑动后,想要View也向右滑动,则要把手机屏幕向着左边滑动,则布局相对向右滑动,实现跟手的效果.

六.Scroller

这个方法的实现效果比较类似动画,不过与动画相比其只可以用来实现滑动效果.

首先要初始化这个scroller:

  1. public CustomView(Context context, AttributeSet attrs) {
  2. super(context, attrs);
  3. scroller=new Scroller(context);
  4. }

接下来重写computeScroll()方法,该方法会在View绘制时的draw()中调用

  1. @Override
  2. public void computeScroll() {
  3. super.computeScroll();
  4. if(scroller.computeScrollOffset()){
  5. ((View)getParent()).scrollTo(scroller.getCurrX(),scroller.getCurrY());
  6. //通过不断调用invalidate(),不断返回调用computeScroll,更新View位置
          // 直到scroller.computeScrolloffset返回fasle(即dutation结束)
          invalidate();
  7. }
  8. }

同时在CustomView中写一个方法:

  1. public void smoothScrollTo(int destX,int dextY){
  2. int scrollX=getScrollX();
  3. int deltaX=destX-scrollX;
  4.  
  5.      //startScroll (int startX, int startY, int dx, int dy, int duration)
  1. scroller.startScroll(scrollX,0,deltaX,0,2000);
  2. invalidate();
  3. }

通过在代码中调用自定义控件的smoothScrollTo方法,可以实现View的滑动效果.

  1.  

View体系第二篇:View滑动的更多相关文章

  1. Android学习笔记(第二篇)View中的五大布局

    PS:人不要低估自己的实力,但是也不能高估自己的能力.凡事谦为本... 学习内容: 1.用户界面View中的五大布局... i.首先介绍一下view的概念   view是什么呢?我们已经知道一个Act ...

  2. View体系第一篇:基础

    View体系的学习内容为学习刘望舒先生博客总结的内容,大家可到他的博客看到更详细的内容. 一.view之间的继承关系 Viewground用来包裹其他view.在平常的使用中,我们不会直接用到View ...

  3. 《Android进阶之光》--View体系与自定义View

    No1: View的滑动 1)layout()方法的 public class CustomView extends View{ private int lastX; private int last ...

  4. Android View体系(一)视图坐标系

    前言 Android View体系是界面编程的核心,他的重要性不亚于Android四大组件,在这个系列中我会陆续讲到View坐标系.View的滑动.View的事件分发等文章来逐步介绍Android V ...

  5. Android View体系(四)从源码解析Scroller

    在Android View体系(二)实现View滑动的六种方法这篇文章中我们讲到了用Scroller来实现View的滑动,所以这篇文章我们就不介绍Scroller是如何使用的了,本篇就从源码来分析下S ...

  6. android自定义View之仿通讯录侧边栏滑动,实现A-Z字母检索

    我们的手机通讯录一般都有这样的效果,如下图: OK,这种效果大家都见得多了,基本上所有的android手机通讯录都有这样的效果.那我们今天就来看看这个效果该怎么实现. 一.概述 1.页面功能分析 整体 ...

  7. Android View体系(三)属性动画

    上一篇文章讲了View滑动的六种方法,其中一种是使用动画,这篇文章我们来讲一讲动画的其中一种:属性动画. 1.android视图动画和属性动画 视图动画我们都了解,它提供了AlphaAnimation ...

  8. Android View体系(八)从源代码解析View的layout和draw流程

    相关文章 Android View体系(一)视图坐标系 Android View体系(二)实现View滑动的六种方法 Android View体系(三)属性动画 Android View体系(四)从源 ...

  9. Android View体系(十)自定义组合控件

    相关文章 Android View体系(一)视图坐标系 Android View体系(二)实现View滑动的六种方法 Android View体系(三)属性动画 Android View体系(四)从源 ...

随机推荐

  1. Django 数据聚合函数 annotate

    统计各个分类下的文章数 2 周,3 日前 字数 3818 阅读 546 评论 21 在我们的博客侧边栏有分类列表,显示博客已有的全部文章分类.现在想在分类名后显示该分类下有多少篇文章,该怎么做呢?最优 ...

  2. [MongoDB]Mongo基本使用

    [MongoDB]Mongo基本使用:   汇总: 1. [MongoDB]安装MongoDB2. [MongoDB]Mongo基本使用:3. [MongoDB]MongoDB的优缺点及与关系型数据库 ...

  3. jetty8 text/plain默认字符编码的坑

    今天在测试一个content-type为text/plain的API时发现后端requestBody乱码了,而线上正常. 自己本地使用jetty8版本,插件自带版本,而线上使用jetty9. 最开始没 ...

  4. Storm WordCount

    特别注意,在本地运行的时候应该去掉<scope>provided</scope>,否则会报java.lang.ClassNotFoundException: org.apach ...

  5. Android主线程的消息系统(Handler\Looper)

    前言: 之前的文章写的都是关于Bitmap和内存的优化技术,这一篇文章给大家谈谈Handler. Handler是Android系统中比较重要的一个知识,在Android多线程面试经常会被问到,在实际 ...

  6. HashMap source code view(1)

    前言 HashMap source code view 类注释 Hash table based implementation of the Map interface. This implement ...

  7. 【EF6学习笔记】(十)处理并发

    本篇原文链接:Handling Concurrency Concurrency Conflicts 并发冲突 发生并发冲突很简单,一个用户点开一条数据进行编辑,另外一个用户同时也点开这条数据进行编辑, ...

  8. Java 容器源码分析之 Set

    Set 表示由无重复对象组成的集合,也是集合框架中重要的一种集合类型,直接扩展自 Collection 接口.在一个 Set 中,不能有两个引用指向同一个对象,或两个指向 null 的引用.如果对象 ...

  9. 【Git】时光机命令—Git命令

    cd c:    进入C盘 mkdir learngit          创建名为learngit的文件夹 cd learngit  进入learngit文件夹 pwd    显示当前目录路径 gi ...

  10. Python网络编程之Socket的简单实现

    一.引入 关于Python的网络编程,最基础莫过于socket了. socket,又称“套接字”,网络上的两个程序如果想要实现双向的数据通信,需要建立连接,这个连接的一端就称为一个socket. py ...