Android Scroll分析(二)——滑动的几种方法

来源:互联网 发布:数据作用 编辑:程序博客网 时间:2024/05/23 02:00

1.实现滑动的基本思想是当触摸view的时候,系统记录当前触摸点的坐标,当手指移动的时候,系统记录下移动后触摸点的坐标,从而花去到相对于前一次的偏移量,并且通过偏移量来修改view的坐标,这样不断的重复,从而实现滑动的过程。

2.下面通过一个实例来看看android是如何实现滑动效果的,自定义一个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:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent">    <com.best.keke.myscrollviewdemo.MyScrollView        android:id="@+id/myscrollview"        android:layout_width="130dp"        android:layout_height="130dp"        android:background="#0000ff"/></LinearLayout>

3.layout方法

我们知道在view进行绘制的时候回调用onLayout()方法来设置显示的位置,同样可以通过修改view的left,top,right,bottom四个属性来控制view的坐标。在每次回调onTouchEvent()的时候,我们都获取下触摸点的坐标:

 int x = (int) event.getX(); int y = (int) event.getY();

接着在MotionEvent.ACTION_DOWN中记录触摸点的坐标:

 case MotionEvent.ACTION_DOWN:     // 按下的坐标点         lastX = x;         lastY = y;         break;

最后在MotionEvent.ACTION_MOVE()中计算偏移量,并且将偏移量作用到layout()方法中。

 case MotionEvent.ACTION_MOVE:         // 计算偏移量                int offsetX = x - lastX;                int offsetY = y - lastY;        // 在当前的left,top,right,bottom基础上加上偏移量                layout(getLeft() + offsetX, getTop() + offsetY,                        getRight() + offsetX, getBottom() + offsetY);                break;

这样移动之后,view都会调用layout方法来重新进行布局,从而达到移动view的效果。

4. offsetTopAndBottom()和 offsetLeftAndRight()方法

该方法提供了相当于向上或者是向下的移动偏移量

// 同时对上下进行偏移offsetTopAndBottom(int offset)// 同时对左右进行偏移offsetLeftAndRight(int offset)

5.LayoutParams

LayoutParams保存了一个view的布局参数,通过改变LayoutParams来动态的修改一个布局 位置信息,从而达到改变view位置的效果。我们哈可以使用getLayoutParams()来获取到一个view的LayoutParams。当然计算偏移量的方法与在layout方法中计算offset也是一样的,当获取到偏移量之后,就 可以通过setLayoutParams()来改LayoutParams。
代码如下:

 RelativeLayout.LayoutParams mLayoutParams = (RelativeLayout.LayoutParams) getLayoutParams();        mLayoutParams.leftMargin = getleft() + offsetX;        mLayoutParams.topMargin = getTop() + offsetY;        setLayoutParams(mLayoutParams);

这里需需要注意的是。通过getLayoutParams()获取到的LayoutParams时,需要根据view在父布局中的类型来设置不同的类型,此处将view放在了RelativeLayout中,那么就要使用RelativeLayout.LayoutParams。类似的在LinearLayout类型中也是一样的。当然获取LayoutParams的前提是必须要先有一个父布局。否则无法获取到LayoutParams。

在改变LayoutParams来改变view的位置时,通常改变的是view的Margin属性,所以除了使用布局的LayoutParams之外,还可以使用

 ViewGroup.MarginLayoutParams mLayoutParams = ( ViewGroup.MarginLayoutParams) getLayoutParams();        mLayoutParams.leftMargin = getleft() + offsetX;        mLayoutParams.topMargin = getTop() + offsetY;        setLayoutParams(mLayoutParams);

这样使用viewgroup的好处就是我们不需要考虑父布局的类型。

5.scrollTo和scrollBy

二者的区别是scrollTo(x,y)表示的是移动到一个具体的坐标点(x,y),而scrollBy(x,y)表示的是移动的增量为dx何dy.
与前面的几种方式类似,在获取偏移量后使用scrollBy来移动view.

int offsetX = x - lastX;int offsetY = y - lastY;scrollBy(offsetX, offsetY);

但是当我么拖动view的时候,发现view并没有移动,移动的不是我们想要的。scrollTo和scrollBy方法移动的是view的content,即让view的内容移动,如果在viewgroup中使用scrollTo和scrollBy,那么移动的将是所有的子view.但是如果在view中使用,移动的将是view的内容,如textview,移动的将是文本信息,imageview中移动的将是drawable对象。综上所述,我们就应该在viewgroup中使用scrollBy方法,移动它的子view.

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

但是当拖动view的时候,我们会发现view在乱动,并不是按照我们跟随触摸点进行的移动。这里需要了解一个知识点:我们可以吧手机屏幕当做是一个中空的盖板,盖板下面是一个巨大的画布,也就是我们要显示的视图,当把盖板盖在画布上的某一处时,透过中间空的矩形,我们就看见了手机屏幕上显示的视图,而画布上其他的视图被盖板挡住了就看不见。如下图所示:
这里写图片描述
如图:中间的矩形相当于手机的屏幕,即可视区域,后面的大矩形相当于是画布,代表的是所有的视图。只有中间的视图是可见的,其他的区域都是不可见的,可见区域的button坐标为(30,15)。

下面使用scrollBy()方法,将盖板子啊水平方向上向X轴正方向平移30,在竖直方向上向Y轴正方向平移15,平移后的视图如右侧所示。

我们可以发现,虽然设置了scrollBy(30,15),偏移量都是在X,Y轴的正方向的正数,但是在屏幕的可视区域内,Button却向X,Y轴的负方向上移动了。

通过以上的分析,我们可以发现,如果将scrollBy中的参数dx和dy设置为正数,那么画布中的内容就将向坐标轴路的负方向移动,如果将scrollBy中的参数dx和dy设置为负数,那么画布中的内容就将向坐标轴路的正方向移动。所以要实现跟随手指移动而滑动的效果,就必须将偏移量改成负值。

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