前几天公司为了提示用户viewpager是能滑动, 要默认进入到界面后,viewpager自身抖动下,然后在恢复到原位.
效果如下,
不对不对,应该是下面的
现在项目中用的viewpager,怎么实现这个东西又简单,有改变的代码最少?
少罗嗦先看东西,实现的效果如下,我们还能加各种动画差值器,
不到十行代码实现这个效果
思路很重要
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;
}
这个方法是辅助方法,用户能力缺陷给开发者带来便利,
/**
* 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本身是一个相框,
是你的相片在动,相框还在原地,就是这么个原理…