View基本参数

一、View的位置参数

1、left、bottom、right、top

(1)left: mLetft = getLeft() View的左上角横坐标
(2)right:mRight = getRight() View的右下角横坐标
(3)top: mTop = getTop() View的左上角纵坐标
(4)bottom: mBottom = getBottom View的右下角纵坐标
这些坐标是相对于View的父容器而言的,是一个相对坐标。

2、x,y

View左上角的坐标,是View在窗口的实际位置。

3、translationX,transactionY

View左上角相对于父容器的偏移量,默认为0。
且有x = left + translationX
View在平移的过程中,top和left是原始左上角的位置信息,其值不会发生改变,此时发生改变的是x、y、translationX,translationY。

二、MotionEvent和TouchSlop

1、MotionEvent

MotionEvent提供了获取事件发生时x和y坐标的获取方法。
getX()/getY() 返回相对于当前View左上角的x和y坐标。
getRawX()/getRawY() 返回相对于手机屏幕左上角的x和y坐标。

2、TouchSlop

系统能识别出的被认为是滑动的最小距离。该值是常量,跟设备有关,不同设备可能是不同的值,该值可用来过滤一些两次滑动事件的距离过小的场景。
获取方式:

ViewConfiguration.get(applicationContext).scaledTouchSlop

三、VelocityTracker、GestureDetector和Scroller

1、VelocityTracker

速度追踪,用于追踪手指在滑动过程中的速度,包括水平速度和竖直速度。

class TempLinearLayout(context: Context) : LinearLayout(context) {
    
    private val velocityTracker: VelocityTracker = VelocityTracker.obtain()


    override fun onTouchEvent(event: MotionEvent?): Boolean {
        
        velocityTracker.addMovement(event)
        
        when(event?.action) {
            
            MotionEvent.ACTION_MOVE -> {
                velocityTracker.computeCurrentVelocity(100) //计算当前速度,指一短时间内手指划过的像素数,传入的值单位ms
                val xVelocity = velocityTracker.xVelocity //速度值是矢量值,带方向,如果从右往左滑速度为负值
                val yVelocity = velocityTracker.yVelocity
            }
            
            MotionEvent.ACTION_UP -> {
                velocityTracker.clear()
                velocityTracker.recycle() //TODO 如果不再使用则recycler
            }
            
        }
        
        return super.onTouchEvent(event)
    }
}

速度 = (终点位置 - 起点位置) / 时间段

2、GestureDetector

手势检测,用于辅助监测用户的单击、滑动、长按、双击等行为。

class TempLinearLayout(context: Context) : LinearLayout(context) {

    private val gestureDetector = GestureDetector(context, object : GestureDetector.OnGestureListener {
        override fun onShowPress(e: MotionEvent?) {
            TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
        }

        override fun onSingleTapUp(e: MotionEvent?): Boolean {
            TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
        }

        override fun onDown(e: MotionEvent?): Boolean {
            TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
        }

        override fun onFling(
            e1: MotionEvent?,
            e2: MotionEvent?,
            velocityX: Float,
            velocityY: Float
        ): Boolean {
            TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
        }

        override fun onScroll(
            e1: MotionEvent?,
            e2: MotionEvent?,
            distanceX: Float,
            distanceY: Float
        ): Boolean {
            TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
        }

        override fun onLongPress(e: MotionEvent?) {
            TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
        }

    })


    override fun onTouchEvent(event: MotionEvent?): Boolean {
        return gestureDetector.onTouchEvent(event) //接管View的onTouchEvent
    }
}
3、Scroller

用于实现View的弹性滑动,可以实现有过渡效果的滑动,其过程不是瞬间完成的,而是在一定的时间间隔内完成,需要与View的computeScroll方法配合使用。

class TempLinearLayout(context: Context) : LinearLayout(context) {
    
    private val scroller: Scroller = Scroller(context)
    
    fun smoothScrollTo(destX: Int, destY: Int) {
        val scrollX = scrollX
        val delta = destX - scrollX
        scroller.startScroll(scrollX, 0, delta, 0, 1000) //duration  单位ms
        invalidate()
    }

    override fun computeScroll() {
        if (scroller.computeScrollOffset()) {
            scrollTo(scroller.currX, scroller.currY)
            postInvalidate()
        }
    }
}
4、scrollBy和scrollTo
    /**
     * Set the scrolled position of your view. This will cause a call to
     * {@link #onScrollChanged(int, int, int, int)} and the view will be
     * invalidated.
     * @param x the x position to scroll to
     * @param y the y position to scroll to
     */
    public void scrollTo(int x, int y) {
        if (mScrollX != x || mScrollY != y) {
            int oldX = mScrollX;
            int oldY = mScrollY;
            mScrollX = x;
            mScrollY = y;
            invalidateParentCaches();
            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
            if (!awakenScrollBars()) {
                postInvalidateOnAnimation();
            }
        }
    }

    /**
     * Move the scrolled position of your view. This will cause a call to
     * {@link #onScrollChanged(int, int, int, int)} and the view will be
     * invalidated.
     * @param x the amount of pixels to scroll by horizontally
     * @param y the amount of pixels to scroll by vertically
     */
    public void scrollBy(int x, int y) {
        scrollTo(mScrollX + x, mScrollY + y);
    }

在滑动过程中,mScrollX的值总等于View左边缘和View内容左边缘在水平方向的距离,mScrollY总等于View上边缘和View内容上边缘在竖直方向的距离。

结尾

摘抄自《Android开发艺术探索》

你可能感兴趣的:(View基本参数)