实现View滑动的方法总结

来源:互联网 发布:西安西科软件 编辑:程序博客网 时间:2024/05/19 08:38

此博客主要介绍基本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。

上述的代码下载请点我

0 0
原创粉丝点击