Android——滚动效果(View内部滚动+拖动滚动)

来源:互联网 发布:windows ping 编辑:程序博客网 时间:2024/06/14 04:09

基础知识准备:

一、在View内部,和滚动相关的类有以下两个

public void scrollTo(int x, int y)          说明:在当前视图内容偏移至(x , y)坐标处,即显示(可视)区域位于(x , y)坐标处。    方法原型为: View.java类中public void scrollBy(int x, int y)            说明:在当前视图内容继续偏移(x , y)个单位,显示(可视)区域也跟着偏移(x,y)个单位。

使用:
scrollTo,将view的左上角(x,y)为标准点进行移动。 调用scrollTo(10, 10)表示将View中的内容移动到x = 10, y = 10的位置

public void scrollBy(int x, int y) { scrollTo(mScrollX + x, mScrollY + y); }  

此处,scrollBy(10,10),相当于scrollTo(x+10,y+10)

二、getScrollX()+getScrollY()

mScrollX:表示离视图起始位置的x水平方向的偏移量
mScrollY:表示离视图起始位置的y垂直方向的偏移量
分别通过getScrollX() 和getScrollY()方法获得。
注意:mScrollX和mScrollY指的并不是坐标,而是偏移量。

三、getX getRowX()getLeft()等方法

MotionEvent类中 getRowX()和 getX()的区别:
event.getRowX():触摸点相对于屏幕原点的x坐标
event.getX(): 触摸点相对于其所在组件原点的x坐标。意思就是说获取到实际的View的x y 值,该值也是相对父视图而言的,并且该值 getX = getLeft + getTraslationX。最后得出的值也是相对父视图来说的。
于是乎: view.getScrollY() + event.getY() 就得到了view中的触摸点在Y轴上的偏移量
这里写图片描述

getLeft , getTop, getBottom, getRight, 这一组是获取相对在它父亲里的坐标

这里写图片描述

四、刷新界面等值

invalidate()是用来刷新View的,必须是在UI线程中进行工作。比如在修改某个view的显示时,调用invalidate()才能看到重新绘制的界面。invalidate()的调用是把之前的旧的view从主UI线程队列中pop掉。

五、View执行过程

view的执行过程onDraw、onSizeChanged,onFinishInflate
在onSizeChanged中,可以获取view的一些位置信息

Demo:

package com.example.zoompro;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.animation.BounceInterpolator;import android.widget.OverScroller;import android.widget.TextView;public class MyJellyTextView extends TextView {    private float startX;    private float startY;    private float downY;    private float downX;    private OverScroller mScroller;    public MyJellyTextView(Context context, AttributeSet attrs) {        super(context, attrs);        mScroller = new OverScroller(context, new BounceInterpolator());    }    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {        case MotionEvent.ACTION_DOWN:            downX = event.getRawX();            downY = event.getRawY();            break;        case MotionEvent.ACTION_MOVE:            //获取在屏幕中的位置            int[] location = new int[2];            getLocationOnScreen(location);            int x = location[0];            int y = location[1];            //控制View的移动范围             if (x > MainActivity.screenWidth*3/5|| x < MainActivity.screenWidth/8) {                break;            }            if (y >MainActivity.screenHeigh*9/10 || y < MainActivity.screenHeigh/5) {                break;            }            float disX = event.getRawX() - downX;            float disY = event.getRawY() - downY;            // 移动 分方向            offsetLeftAndRight((int) disX);            offsetTopAndBottom((int) disY);            downX = event.getRawX();            downY = event.getRawY();            break;        case MotionEvent.ACTION_UP:            // 反弹回原来的位置            mScroller.startScroll((int) getX(), (int) getY(), -(int) (getX() - startX), -(int) (getY() - startY));            invalidate();//这里必须调用invalidate()才能保证computeScroll()会被调用,否则不一定会刷新界面,看不到滚动效果              break;        default:            break;        }        return super.onTouchEvent(event);    }    @Override    public void computeScroll() {        if (mScroller.computeScrollOffset()) {            setX(mScroller.getCurrX());            setY(mScroller.getCurrY());            invalidate();        }    }    // view的执行过程onDraw、onSizeChanged,onFinishInflate    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        startX = getX();        startY = getY();    }}
0 0