1.View的滑动简介

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

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

layout()

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

首先我们要自定义一个View,在onTouchEvent()方法中获取触摸点的坐标:
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; 接下来我们在ACTION_MOVE事件中计算偏移量,再调用layout()方法重新放置这个自定义View的位置就好了
case MotionEvent.ACTION_MOVE:
//计算移动的距离
int offsetX = x - lastX;
int offsetY = y - lastY;
//调用layout方法来重新放置它的位置
layout(getLeft()+offsetX, getTop()+offsetY,
getRight()+offsetX , getBottom()+offsetY);
break; 当我们每次移动时都会调用layout()方法来对自己重新布局,从而达到移动View的效果。 自定义View的全部代码(CustomView.java):
public class CustomView extends View {
private int lastX;
private int lastY; public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
} public CustomView(Context context) {
super(context);
} 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方法来重新放置它的位置
layout(getLeft()+offsetX, getTop()+offsetY,
getRight()+offsetX , getBottom()+offsetY);
break;
} return true;
}
} 布局中引用自定义View:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <com.example.liuwangshu.moonviewslide.CustomView
android:id="@+id/customview"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_margin="50dp"
android:background="@android:color/holo_red_light" />
</LinearLayout>

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;

LayoutParams(改变布局参数)

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

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

动画

可以采用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="" android:toXDelta="" android:duration=""/>
</set> 在Java代码中引用:
mCustomView.setAnimation(AnimationUtils.loadAnimation(this, R.anim.translate)); 当然使用属性动画移动那就更简单了,我们让CustomView在1000毫秒内沿着X轴像右平移300像素:
ObjectAnimator.ofFloat(mCustomView,"translationX",,).setDuration().start();

scollTo与scollBy

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

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

Scroller

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

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

3.完整代码:

public class ViewSlideActivity extends AppCompatActivity {
private CustomView mCustomView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_slide);
mCustomView= (CustomView) this.findViewById(R.id.customview);
//使用属性动画使view滑动
// ObjectAnimator.ofFloat(mCustomView,"translationX",0,300).setDuration(1000).start();
//使用View动画使view滑动
// mCustomView.setAnimation(AnimationUtils.loadAnimation(this, R.anim.translate));
//使用Scroll来进行平滑移动
mCustomView.smoothScrollTo(-,);
}
} public class CustomView extends View {
private int lastX;
private int lastY;
private Scroller mScroller; public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); } public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
mScroller = new Scroller(context);
} public CustomView(Context context) {
super(context);
} 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方法来重新放置它的位置
// layout(getLeft()+offsetX, getTop()+offsetY,
// getRight()+offsetX , getBottom()+offsetY); //对left和right进行偏移
// offsetLeftAndRight(offsetX);
//对top和bottom进行偏移
// offsetTopAndBottom(offsetY);
//使用LayoutParams
// LinearLayout.LayoutParams layoutParams= (LinearLayout.LayoutParams) getLayoutParams();
// layoutParams.leftMargin = getLeft() + offsetX;
// layoutParams.topMargin = getTop() + offsetY;
// setLayoutParams(layoutParams); //使用MarginLayoutParams
// ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams();
// layoutParams.leftMargin = getLeft() + offsetX;
// layoutParams.topMargin = getTop() + offsetY;
// setLayoutParams(layoutParams);
//使用scrollBy
((View)getParent()).scrollBy(-offsetX,-offsetY);
break;
} return true;
}
public void smoothScrollTo(int destX,int destY){
int scrollX=getScrollX();
int delta=destX-scrollX;
//1000秒内滑向destX
mScroller.startScroll(scrollX,,delta,,);
invalidate();
}
@Override
public void computeScroll() {
super.computeScroll();
if(mScroller.computeScrollOffset()){
((View) getParent()).scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
//通过不断的重绘不断的调用computeScroll方法
invalidate();
} }
}

Android View体系(二)实现View滑动的六种方法的更多相关文章

  1. android中实现view可以滑动的六种方法续篇(二)

    承接上一篇,上一篇中讲解了实现滑动的第五种方法,如果你还没读过,可点击下面链接: http://www.cnblogs.com/fuly550871915/p/4985482.html 这篇文章现在来 ...

  2. android中实现view可以滑动的六种方法

    在android开发中,经常会遇到一个view需要它能够支持滑动的需求.今天就来总结实现其滑动的六种方法.其实每一种方法的 思路都是一样的,即:监听手势触摸的坐标来实现view坐标的变化,从而实现vi ...

  3. android中实现view可以滑动的六种方法续篇(一)

    承接上一篇,如果你没有读过前四章方法,可以点击下面的链接: http://www.cnblogs.com/fuly550871915/p/4985053.html 下面开始讲第五中方法. 五.利用Sc ...

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

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

  5. View体系第二篇:View滑动

    View滑动的基本思想:当点击事件传到View时,系统记下触摸点的坐标,手指移动时系统记下触摸后的坐标并计算出偏移量,然后根据偏移量修正View坐标. 实现View滑动共有6种方法:layout()方 ...

  6. Android动画之二:View Animation

    作为一个博客<Android其中的动画:Drawable Animation>.android动画主要分为三大部分.上一篇博客已经解说Drawable Animation的使用方法,即逐帧 ...

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

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

  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. SQL-2--TRIGGER

    触发器TRIGGER 是一个被指定关联到一个表的数据库对象,当对一个表的特定事件出现时,它将被激活. 触发器是数据库响应 INSERT , UPDATE, DELITE 语句而自动执行的一条SQL语句 ...

  2. LDO和DC-DC的概念,区别及优缺点

    最近在做蓝牙项目的时候,遇到了需要配置这两种不同的供电模式的问题,这里顺便温习一下这种供电方式的概念,做个总结. LDO :LOW DROPOUT VOLTAGE 低压差线性稳压器,故名思意,为线性的 ...

  3. win10 插入16k采样的耳机无法播放和录音的问题定位

    平时做智能耳机,需要经常在windows上测试不同采样率的声音信号.可是,最近在16k双声道输入的情况下, 无论系统都使用该耳机进行播放,该问题思索了好久,一直没有解决办法. 今天无意中使用了wind ...

  4. python 中numpy中函数hstack用法和作用

    定义: Stack arrays in sequence horizontally (column wise). Take a sequence of arrays and stack them ho ...

  5. 一个隐蔽的C语言问题反思

    今天在编译一个C代码的时候,从别的编译ok的头文件中拷贝了一份在上面做修改,没想到修改好之后一直 无法调用这个头文件中的函数和变量.看了好久,才在预编译宏中找到了问题的根源.代码 如下所示: 头文件A ...

  6. 关于appendChild和insertBefore appendTo()和append

    appendChild和insertBefore(原生js) appendTo()和append(jquery)

  7. Django--分页器(paginator)

    1 Django的分页器(paginator)简介 在页面显示分页数据,需要用到Django分页器组件 from django.core.paginator import Paginator Pagi ...

  8. sql server 备份与恢复系列七 页面还原

    一.概述 当数据库发生损坏,数据库的每个文件都能打开,只是其中的一些页面坏了,这种情况可以借助DBCC CHECKDB进行数据库检查修复.如果要保证数据库不丢失,或修复不好,管理员只能做数据库完整恢复 ...

  9. 字符串replaceAll()方法报错:java.util.regex.PatternSyntaxException:Unclosed group near index...

    Unclosed group near index错误 之前自己写的一个模块在项目上线后最近频频出现tomcat崩掉的情况,从log看出现如下的报错信息: java.util.regex.Patter ...

  10. 如何设计和实现高可用的MySQL

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯云数据库 TencentDB发表于云+社区专栏 王甲坤,腾讯高级工程师.腾讯云关系型数据库MySQL负责人,拥有多年客户端.数据库 ...