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

基础知识准备:

一、在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轴上的偏移量
Android——滚动效果(View内部滚动+拖动滚动)_第1张图片

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

Android——滚动效果(View内部滚动+拖动滚动)_第2张图片

四、刷新界面等值

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();
    }
}

你可能感兴趣的:(自定义组件,Android)