美文网首页Android
Android View的滑动和滑动冲突

Android View的滑动和滑动冲突

作者: 漆先生 | 来源:发表于2022-03-09 22:47 被阅读0次

一、View的滑动

可以通过三种方式实现滑动。

  • 通过View本身提供的scrollTo和scrollBy方法来实现滑动
  • 通过动画给View施加平移效果来实现滑动
  • 通过改变View的LayoutParams使得View重新布局从而实现滑动

1.使用scrollTo和scrollBy

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

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

scrollBy实际调用了scrollTo,实现了相对于当前位置的相对滑动。scrollTo实现了基于所传递参数的绝对滑动。
scrollTo和scrollBy只能改变View的内容位置,而不能改变View在布局中的位置。
mScrollX的值暂时等于View左边缘和View内容左边缘在水平方向的距离,内容在View的左边,为正值,反之为负值
mScrollY的值总是等于View上边缘和View内容上边缘在竖直方向的距离,内容在View的上边,为正值,反之为负值

2.使用动画

使用动画来移动移动View,主要是操作View的translationX和translationY属性。可以选择传动的View动画,也可以选择属性动画。

加载xml动画100ms把View移动到右下角100个像素,新位置只是View的影像,点击目标view会触发click。

<?xml version="1.0" encoding="utf-8"?>
<!--fillAfter = true设置停留在动画后的音像-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true"
    android:zAdjustment="normal">
    <translate
        android:duration="100"
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:interpolator="@android:anim/linear_interpolator"
        android:toXDelta="100"
        android:toYDelta="100" />
</set>

val animation = AnimationUtils.loadAnimation(this@MainActivity, R.anim.translate_100)
v.startAnimation(animation)

属性动画,将View右移动100像素,点击目标View,不会触发click。

ObjectAnimator.ofFloat(v, "translationX", 0f, 100f).setDuration(100).start()

3.改变布局参数

修改LayoutPrams的值达到滑动效果,右移100px

val params: ViewGroup.MarginLayoutParams =
    textView.layoutParams as ViewGroup.MarginLayoutParams
params.leftMargin += 100
v.requestLayout()
//v.layoutParams = params

4.对比总结

  • scrollTo和scrollBy:操作简单,View提供的原生方法,适合View内容的滑动。不影响元素的单击事件。缺点是只能移动内容,不能移动View本身。
  • 动画:属性动画没有明显缺点,如果是使用xml动画,不能改变View本身的属性。如果动画元素不需要响应用户的交互,使用动画来做滑动比较合适。并且还能实现复杂的效果。
  • 改变布局参数:使用麻烦一点,没有明显缺点,适用于动画元素是一些具有交互性的View。

二、弹性滑动

1.使用Scroller

    public void smoothScrollTo(int destX, int destY) {
        int scrollX = getScrollX();
        int scrollY = getScrollY();
        mScroller.startScroll(scrollX, scrollY, destX, destY, 1000);
        invalidate();
    }

    public void computeScroll() {
        super.computeScroll();
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), mScroller.getCurrX());
            postInvalidate();
        }
    }

    public void startScroll(int startX, int startY, int dx, int dy, int duration) {
        mMode = SCROLL_MODE;
        mFinished = false;
        mDuration = duration;
        mStartTime = AnimationUtils.currentAnimationTimeMillis();
        mStartX = startX;
        mStartY = startY;
        mFinalX = startX + dx;
        mFinalY = startY + dy;
        mDeltaX = dx;
        mDeltaY = dy;
        mDurationReciprocal = 1.0f / (float) mDuration;
    }

startScroll是无法让View滑动的,因为它内部并没有做滑动相关的事情。startScroll方法下面有一个invalidate方法,会导致View重绘,在View的onDraw方法就会去调用computeScroll方法,computeScroll在View中是一个空的实现。我们在实现时,又去向scroller获取当前的scrollX和scrollY,再用scrollTo方法实现滚动,接着又调用postInvalidate方法进行第二次重绘,如此反复,就完成了滑动的整个过程。

2.通过动画

动画本身就是一个渐进的过程,天然的具有弹性效果,如上面的属性动画。

ObjectAnimator.ofFloat(v, "translationX", 0f, 100f).setDuration(100).start()

3.使用延迟策略

核心思想是通过发送一系列的延迟消息从而达到渐进时的效果。可以使用Handler或者View的postDelayed方法,也可以使用线程的sleep方法。

三、View的滑动冲突

1.常见的滑动冲突场景

  • 外部滑动方向和内部滑动方向不一致
  • 外部滑动方向和内部滑动方向一致
  • 以上两种情况嵌套

2.滑动冲突的解决方式

  • 外部拦截法,父容器需要此事件就拦截,不需要就不拦截。重写父容器的onInterceptTouch
    Event方法就行。
  • 内部拦截法,父容器不拦截任何事件,所有事件都传递给子元素,如果子元素需要此事件就直接消耗掉,否则就交由父容器进行处理。需要配合requestDisallowInterceptTouchEvent方法使用。

相关文章

网友评论

    本文标题:Android View的滑动和滑动冲突

    本文链接:https://www.haomeiwen.com/subject/reptdrtx.html