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

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

一.layout()

import ...;

public class CustomView extends View {
private int lastX;
private int lastY; public CustomView(Context context) {
super(context);
} public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
} public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
} public CustomView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
} @Override
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;
        //修改View的left,top,right,bottom属性重新放置View
layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);
break;
}
return true;
}
}

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

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical"
> <com.example.scroll_test.CustomView
android:layout_width="80dp"
android:layout_height="80dp"
android:background="@color/colorAccent"
/> </LinearLayout>

二.offsetLeftandRight

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

            case MotionEvent.ACTION_MOVE:
int offsetX = x - lastX;
int offsetY = y - lastY;
offsetLeftAndRight(offsetX);
offsetTopAndBottom(offsetY);
break;
}

三.LayoutParams(改变布局参数)

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

将ACTION_MOVE修改成以下代码:

            case MotionEvent.ACTION_MOVE:
int offsetX = x - lastX;
int offsetY = y - lastY;
          
LinearLayout.LayoutParams layoutParams= (LinearLayout.LayoutParams) getLayoutParams();
layoutParams.leftMargin=getLeft() + offsetX;
layoutParams.topMargin=getTop() + offsetY;
setLayoutParams(layoutParams);
break;
}

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

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

四.属性动画

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替换成如下代码:

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

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

六.Scroller

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

首先要初始化这个scroller:

public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
scroller=new Scroller(context);
}

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

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

同时在CustomView中写一个方法:

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

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

												

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. 我面试过没有上万人也有十几个,简历要这么写才有hr要你

    今天终于有时间好好给大家写写关于如何写简历,给自己加分了. 这篇文章拖了很久了应该说,本来想在上周写的,但是事情实在是太多,又不想草草了事,所以搁置到现在.今天早上正好空出来了,就马上给大家码出来了. ...

  2. eslint prettier editrorconfig - 写出干净的前端代码

    FConfidence 关注 2018.12.30 02:38* 字数 2912 阅读 195评论 0喜欢 0 VSCode 插件安装 Prettier - Code Formatter ESLint ...

  3. Mac 下使用svn

    作为一个一直使用windows系统的人,还真不知道mac上的svn如何使用,偶然机会下现在需要. 查过后发现 mac 是自带svn的,在我装好xcode后,再安装 Command Line Tools ...

  4. Zabbix系列之五——监控TCP端口

    监控端口的几个主要Keys: net.tcp.listen[port] Checks if this port is in LISTEN state. 0 - it is not, 1 - it is ...

  5. Android--UI之Button

    前言 最近一直在讲androidUI控件的使用方式,这篇博客讲解一下基本上属于用处最广泛的控件之一的Button控件.如果有过其他平台开发经验的程序员,对按钮是不会陌生的.本篇博客首先讲解一下Andr ...

  6. 【干货】Jquery.Datables与Bootstrap3的组合使用

    官方地址 datatables官方网址:www.datatables.net 下载bootstrap3与datables文件包 引用文件 css:bootstrap.css.dataTables.bo ...

  7. Docker 快速入门之 Dockerfile

    在 Docker 中我们可以从名为 Dockerfile 的文件中读取指令并且自动构建镜像.在本文中,将介绍 Dockerfile 的基本语法以及基本知识. Dockerfile 是什么 Docker ...

  8. sshfs基于ssh挂载远程目录

    为了像本地一样访问远程主机上的目录,通常我们会在远程主机上使用nfs来导出目录,并在本地主机上mount这个nfs文件系统.如果是windows系统,则使用cifs或samba的方式来访问. 但可能我 ...

  9. [转]Xcode编译生成ipa文件(因为两种证书所以打两个ipa)

    本文转自:https://blog.csdn.net/aisemi/article/details/78305795 1.生成Archive文档a) 需将左上角红色方框里的设备类型选为ios devi ...

  10. 线程 线程池 Task

    首先声明 这是读了 愉悦的绅士 文章 <菜鸟之旅——学习线程(线程和线程池)> <Task与线程> 的一些个人总结,还是那句话,如有不对,欢迎指正 文章以代码加注释的方法展示. ...