实现View滑动的方法总结

本文深入探讨了Android中实现View滑动的三种方法:使用ScrollBy/ScrollTo、动画以及修改LayoutParams属性值,并提供了具体示例代码,旨在帮助开发者理解和实践自定义控件的滑动效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

此博客主要介绍基本View滑动的实现方法,主要方法如下:
1、利用ScrollBy/ScrollTo方法实现;
2、利用动画的方法实现;
3、通过更改View的LayoutParams的属性值来实现。

View滑动的重要性:掌握滑动的方法是实现绚丽的自定义控件的基础。

一、利用ScrollTo/ScrollBy方法实现View的滑动

首先我们要明白View内部的两个属性mScrollX、mScrollY的值的改变规则,如下:
这里写图片描述
如上图所示,mScrollX = x1-x2,即起始位置的横坐标减去末位置的横坐标;mScrollY = y1 - y2,即起始位置的纵坐标减去末位置的纵坐标。

然后需要知道MotionEvent对象中有两组方法:getX()/getY()和getRawX()/getRawY(),它们的区别:getX()/getY()返回的是相对于当前View左上角的x和y坐标,而getRawX()和getRawY()返回的是相对于手机屏幕左上角的x和y坐标。

其次ScrollTo/ScrollBy方法只能滑动该View的内部控件(内容),如:LinearLayout布局中有一个ImageView,当给LinearLayout.scrollTo(….)的时候,滑动的是ImageView,如果该Linearlayout中有多个控件,那么这些控件就一起滑动。

最后写个demo,如下:
布局文件:scroll_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/scroll_text_view"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:text="利用ScrollTo/ScrollBy实现View的滑动"
        android:textColor="#ffffff"
        android:textSize="18sp"
        android:background="#f7aa03"
        android:gravity="center"
        />
    <LinearLayout
        android:id="@+id/scroll_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        >
        <ImageView
            android:id="@+id/scroll_image_view"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:src="@mipmap/ic_launcher"
            android:background="#f20905"
            />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:text="测试text"
            android:gravity="center"
            android:textColor="#000"
            android:background="#14d935"
            />
    </LinearLayout>
</LinearLayout>

逻辑代码:ScrollActivity.java

public class ScrollActivity extends Activity {

    private LinearLayout scrollLayout;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.scroll_layout);

        initView();
    }

    private void initView() {
        scrollLayout = (LinearLayout) findViewById(R.id.scroll_layout);

        scrollLayout.setOnTouchListener(new View.OnTouchListener() {

            //每次移动的起始位置
            float x;
            float y;

            @Override
            public boolean onTouch(View v, MotionEvent event) {

                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        //初始化起始位置
                        x = event.getX();
                        y = event.getY();
                        break;
                    case MotionEvent.ACTION_MOVE:

                        //当前的位置
                        float mX = event.getX();
                        float mY = event.getY();

                        //移动的距离
                        int dx = (int) (x - mX);
                        int dy = (int) (y - mY);

                        scrollLayout.scrollBy(dx, dy);

                        //重置起始位置
                        x = mX;
                        y = mY;
                        break;
                    case MotionEvent.ACTION_UP:
                        break;
                    default:
                        break;
                }
                return true;
            }
        });
    }
}

这部分代码使用ScrollBy()方法实现的,我们还可以用ScrollTo()来实现,就是把上述的scrollLayout.setOnTouchListener()这段代码换成下面的代码即可:

scrollLayout.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                switch (event.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        break;
                    case MotionEvent.ACTION_MOVE:
                        //控件的末位置
                        int x = (int)event.getX();
                        int y = (int)event.getY();
                        scrollLayout.scrollTo(-x, -y);
                        break;
                    case MotionEvent.ACTION_UP:
                        break;
                    default:
                        break;

                }
                return true;
            }
        });

对比ScrollBy()和ScrollTo()方法:
ScrollTo()在滑动到时候,手指按到的部位始终是滑动控件到左上角,体验不是很好;而ScrollBy()方法就不一样了,手指点哪儿就是那儿。

二、利用动画实现View的滑动

demo:
在一个界面中有一个按钮button,一个ImageView,button控制ImageView的滑动,如下:

        animationButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
           //意思是从起始位置平移500像素
             ObjectAnimator.ofFloat(animationImageView,"translationX",0,500).setDuration(100).start();
            }
        });

如上代码中,animationButton控制着animationImageView的平移。在动画中还可以做很多酷炫的滑动,详情会在后续博客中介绍。

三、通过更改View的LayoutParams的参数值来滑动

详情请看代码

public class ParamsActivity extends Activity {

    private ImageView paramsImageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.params_layout);

        initView();
    }

    private void initView() {
        paramsImageView = (ImageView) findViewById(R.id.params_image_view);
        paramsImageView.setOnTouchListener(new View.OnTouchListener() {

            //手指按下去的坐标
            float x;
            float y;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:

                        //初始化手指坐标
                        x = event.getRawX();
                        y = event.getRawY();
                        break;
                    case MotionEvent.ACTION_MOVE:

                        //移动的坐标,
                        float mx = event.getRawX();
                        float my = event.getRawY();

                        //移动的距离
                        int dx = (int) (mx - x);
                        int dy = (int) (my - y);

                        //滑动View
                        setParamsImageViewLayoutParams(dx, dy);

                        //重置手指的坐标
                        x = mx;
                        y = my;
                        break;
                    default:
                        break;
                }
                return true;
            }
        });
    }

    private void setParamsImageViewLayoutParams(int dx, int dy) {

        ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) paramsImageView.getLayoutParams();
        params.leftMargin += dx;
        params.topMargin += dy;
        paramsImageView.requestLayout();
    }

}

注意:
0、我在计算移动距离时,是用末位置的坐标减去起始位置的坐标;

1、我是利用event.getRawX()/event.getRawY()来获取坐标的,因为如果利用getX()/getY()的时候,当手指滑动的时候,View总是慢了一拍,不灵活;而getRawX()/getRawY()就紧跟手指移动,很灵活。

2、在更改LayoutParams参数时,我只是更改了leftMargin和topMargin的值,那能不能通过更改rightMargin和bottomMargin 的值来滑动View呢?答案是不能的,原因应该是控件从左上角开始,本来就跟父布局的右边、底部就有很大的距离,当设置的rightMargin和bottomMargin小于这个距离时,就不起作用了,所以最好去设置leftMargin和bottomMargin。

总结:
1、ScrollBy/ScrollTo是只能移动View内部的内容,即如果给一个View设置了scrollTo/scrollBy,则只能移动该View内部的控件,且View内部的控件一起移动;

2、我用的动画是属性动画,它可以规定在一定的时间内完成,在用的时候,最好是有一个触发的信息;

3、通过更改LayoutParams参数值的方法比较好(个人感觉),它跟scrollTo方法不同,它移动的就是它本身,即如果给一个View设置了onTouchListener,然后在其中移动事件,改变该View的params参数值,就可实现滑动的效果,切记获取坐标时,用getRawX。

上述的代码下载请点我

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值