Android_viewpager抖动效果

前几天公司为了提示用户viewpager是能滑动, 要默认进入到界面后,viewpager自身抖动下,然后在恢复到原位.
效果如下,
Android_viewpager抖动效果_第1张图片

不对不对,应该是下面的

Android_viewpager抖动效果_第2张图片

现在项目中用的viewpager,怎么实现这个东西又简单,有改变的代码最少?
少罗嗦先看东西,实现的效果如下,我们还能加各种动画差值器,

Android_viewpager抖动效果_第3张图片

不到十行代码实现这个效果
思路很重要
1. 手不触摸屏幕的情况下,模拟点击事件,我们知道有一个preonclick

/**
     * Call this view's OnClickListener, if it is defined.  Performs all normal
     * actions associated with clicking: reporting accessibility event, playing
     * a sound, etc.
     *
     * @return True there was an assigned OnClickListener that was called, false
     *         otherwise is returned.
     */
    public boolean performClick() {
        final boolean result;
        final ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnClickListener != null) {
            playSoundEffect(SoundEffectConstants.CLICK);
            li.mOnClickListener.onClick(this);
            result = true;
        } else {
            result = false;
        }

   sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
        return result;
    }

这个方法是辅助方法,用户能力缺陷给开发者带来便利,

  1. 我们能确认的是让viewpager默认的移动一段距离恢复到原来的位置,肯定没有preonTouch,但是viewpager的移动确实要手指触摸,才能滑动,显示第二页.
  2. 继续思考,viewpager的自带API,显示第几页的API
  /**
     * Set the currently selected page. If the ViewPager has already been through its first
     * layout with its current adapter there will be a smooth animated transition between
     * the current item and the specified item.
     *
     * @param item Item index to select
     */
    public void setCurrentItem(int item) {
        mPopulatePending = false;
        setCurrentItemInternal(item, !mFirstLayout, false);
    }

指定item的postion,viewpager能滚动到具体的页面,但是我们的需求是抖一抖,那么我们加入可以传入小数的话,是不是可以滚动到一个item的一半,或者一小半,显然API不支持

3.显示实现方案很明确,手动调用源码的滚动方法,传入自己需要的距离即可

void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) {
        if (mAdapter == null || mAdapter.getCount() <= 0) {
            setScrollingCacheEnabled(false);
            return;
        }
        if (!always && mCurItem == item && mItems.size() != 0) {
            setScrollingCacheEnabled(false);
            return;
        }

        if (item < 0) {
            item = 0;
        } else if (item >= mAdapter.getCount()) {
            item = mAdapter.getCount() - 1;
        }
        final int pageLimit = mOffscreenPageLimit;
        if (item > (mCurItem + pageLimit) || item < (mCurItem - pageLimit)) {
            // We are doing a jump by more than one page.  To avoid
            // glitches, we want to keep all current pages in the view
            // until the scroll ends.
            for (int i = 0; i < mItems.size(); i++) {
                mItems.get(i).scrolling = true;
            }
        }
        final boolean dispatchSelected = mCurItem != item;

        if (mFirstLayout) {
            // We don't have any idea how big we are yet and shouldn't have any pages either.
            // Just set things up and let the pending layout handle things.
            mCurItem = item;
            if (dispatchSelected) {
                dispatchOnPageSelected(item);
            }
            requestLayout();
        } else {
            populate(item);
            // 重点,这里是滑动到具体item的实现,继续追
            scrollToItem(item, smoothScroll, velocity, dispatchSelected);
        }
    }
  private void scrollToItem(int item, boolean smoothScroll, int velocity,
            boolean dispatchSelected) {
        final ItemInfo curInfo = infoForPosition(item);
        int destX = 0;
        if (curInfo != null) {
            final int width = getClientWidth();
            destX = (int) (width * Math.max(mFirstOffset,
                    Math.min(curInfo.offset, mLastOffset)));
        }
        if (smoothScroll) {
            smoothScrollTo(destX, 0, velocity);
            if (dispatchSelected) {
                dispatchOnPageSelected(item);
            }
        } else {
            if (dispatchSelected) {
                dispatchOnPageSelected(item);
            }
            completeScroll(false);
            // 有没有,答案在这里,好了这个需求我们实现了,不就是调用下srollto吗
            scrollTo(destX, 0);
            pageScrolled(destX);
        }
    }

4.看我们如何实现,关于scrollto和srollby自己动手看区别这里不描述了,by也是调用to等等…….

// 就这一个方法实现了刚才的需求,还能抖一抖
 private void shakeAnim() {
        final ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1.F, 0);
        valueAnimator.setDuration(500);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Float current = (Float) animation.getAnimatedValue();
                viewPager.scrollTo((int) (current * shakeLimit), 0);
            }
        });
        // 抖动的插值器
        valueAnimator.setInterpolator(new BounceInterpolator());
        valueAnimator.start();
    }

好了,由于需求比较简单,项目就不上传了,一个方法搞定,这里解释下,scrllto为什么能实现,刚才的抖动效果?scrollto他作用的动画,注意不是viewpager本身,是viewpager里面的内容,也就是你要滑动的内容,而viewpager本身是一个相框,
是你的相片在动,相框还在原地,就是这么个原理…

你可能感兴趣的:(Android系列)