Android详解View的滑动

前言

我们上节讲解了Android坐标系,接下来我们讲解View的滑动。View的滑动时Android实现自定义的基础班。同时在开发中我们也难免会遇到View的滑动处理。其实不管哪种滑动方式,其基本的思想都是类似的:当点击事件传到View时,系统记下触摸点的坐标,手指移动时系统记下移动后触摸的坐标系并计算出偏移量,并通过便宜量来修改View的坐标。实现View的方法有很多种方法,这里主要说一下layout(),offsetLeftAndRight(),offsetTopAndBottom(),LayoutParams,动画,scrollTo,scrollBy,及scroller。


1.layout()方法

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


@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;

接下来我们在ACTION_MOVE事件计算偏移量,再调用layout()方法重新放置这个自定义View的位置即可。代码如下:


case MotionEvent.ACTION_MOVE:
    //计算移动的距离
    int offfsetX = x - lastX;
    int offfsetY = x - lastY;

    //重新布局
    layout(getLeft() + offfsetX,
            getTop() + offfsetY,
            getRight() + offfsetX,
            getBottom() + offfsetY);
    break;

在每次移动调用layout()方法都要重新布局,从而达到移动View的效果。自定义View如下代码:


public class CustomeView extends View {
    private int lastX, lastY;

    public CustomeView(Context context) {
        super(context);
    }

    public CustomeView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @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 offfsetX = x - lastX;
                int offfsetY = x - lastY;

                //重新布局
                layout(getLeft() + offfsetX,
                        getTop() + offfsetY,
                        getRight() + offfsetX,
                        getBottom() + offfsetY);
                break;
        }
        return true;
    }
}

随后,我们在布局中引用自定义View就OK了,xml布局代码如下:


<?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">

    <com.example.administrator.mypermission.view.CustomeView
        android:id="@+id/tv_callPhone"
        android:layout_width="50dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"/>

</LinearLayout>


2.offsetLeftAndRight()与offsetTopAndBottom()

    这两种方法和layout()方法效果差不多,代码如下:


case MotionEvent.ACTION_MOVE:
                //计算移动的距离
                int offfsetX = x - lastX;
                int offfsetY = x - lastY;

                //重新布局
//                layout(getLeft() + offfsetX,
//                        getTop() + offfsetY,
//                        getRight() + offfsetX,
//                        getBottom() + offfsetY);

                //对left和right进行偏移
                offsetLeftAndRight(offfsetX);
                //对top和bottom进行偏移

                offsetTopAndBottom(offfsetY);
                break;


3.LayoutParams改变布局参数

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


case MotionEvent.ACTION_MOVE:
    //计算移动的距离
    int offfsetX = x - lastX;
    int offfsetY = x - lastY;


    LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams();
    layoutParams.leftMargin = getLeft()+offfsetX;
    layoutParams.topMargin = getLeft()+offfsetY;
    setLayoutParams(layoutParams);
    break;


4.动画

    可以采用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>

接下来代码中调用,代码如下:

mCoustome.setAnimation(

AnimationUtils.loadAnimation(this,R.anim.translate))

运行程序,我们设置的控件会向右平移300像素,然后又回到原来的位置。为了解决这个问题,我们需要在tanslate.xml中加上fillAfter = “true”,代码如下。运行代码后会发现,控件向右平移300像素后就停留当前的位置。


<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true">

    <translate
        android:fromXDelta="0"
        android:toXDelta="300"
        android:duration="1000"/>
</set>
续。。。。。。。。

 
 



猜你喜欢

转载自blog.csdn.net/u014133119/article/details/80889548