ViewPager управляем временем анимации переходов

от автора

Добрый день,

Недавно мне понадобилось сделать банерную галерейку с анимацией, проблема была с временем анимации и самой анимацией в ViewPager Переход был слишком быстрый, и если переходить с 1 элемента на 5 то не увидишь анимации 3-4 элементов

Приступим

Давайте попробуем разобраться в чем причина такого поведения ViewPager

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; // Из-за данной строчки во время анимации мы не видим n-ые элементы          if (item > (mCurItem + pageLimit) || item < (mCurItem - pageLimit)) {             for (int i=0; i<mItems.size(); i++) {                 mItems.get(i).scrolling = true;             }         }         final boolean dispatchSelected = mCurItem != item;          if (mFirstLayout) {             mCurItem = item;             if (dispatchSelected && mOnPageChangeListener != null) {                 mOnPageChangeListener.onPageSelected(item);             }             if (dispatchSelected && mInternalPageChangeListener != null) {                 mInternalPageChangeListener.onPageSelected(item);             }             requestLayout();         } else {             populate(item);             scrollToItem(item, smoothScroll, velocity, dispatchSelected); // Здесь происходит анимация до y позиции и тут же высчитывается время анимации         }     } 

Мы разобрали причину почему мы невидим анимации некоторых элементов в ViewPager теперь посмотри как же устроенна функция скроллинга до определенного элемента.

   // зайдем в SmoothScrolltTo и посмотрим как высчитывается время анимации          int duration = 0; //время анимации         velocity = Math.abs(velocity); // скорость         if (velocity > 0) {               duration = 4 * Math.round(1000 * Math.abs(distance / velocity));         } else {             final float pageWidth = width * mAdapter.getPageWidth(mCurItem);             final float pageDelta = (float) Math.abs(dx) / (pageWidth + mPageMargin);             duration = (int) ((pageDelta + 1) * 100);         }         duration = Math.min(duration, MAX_SETTLE_DURATION);          mScroller.startScroll(sx, sy, dx, dy, duration);  

Наверное здесь не нужно много объяснений, все предельно просто. Теперь приступим к добавлю нашего метода для скроллинга с произвольным временем за основу возьмем метод setCurrentItemInternal и smoothScrollTo итак преступим

     public void setCurrentItem( int item, int duration){         if (mAdapter == null || mAdapter.getCount() <= 0) {             setScrollingCacheEnabled(false);             return;         }          int oldCurrentPos = getCurrentItem(); // запоминаем позицию          if(oldCurrentPos == item){ // если нынешняя позиция равна элементу к которому нужно прокрутить возвращаемся             return;         }else{ // иначе выставляем отображение под элементов равное прокручиваемым элементам             setOffscreenPageLimit(Math.abs(oldCurrentPos - item));         }          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 && mOnPageChangeListener != null) {                 mOnPageChangeListener.onPageSelected(item);             }             if (dispatchSelected && mInternalPageChangeListener != null) {                 mInternalPageChangeListener.onPageSelected(item);             }             requestLayout();         } else {             populate(item);              final ItemInfo curItem = infoForPosition(item);             int destX = 0;             if(curItem != null){                 final int width = getClientWidth();                 destX = (int) (width * Math.max(mFirstOffset, Math.min(curItem.offset, mLastOffset)));             }              if(duration > 0){                  int velocity = duration / Math.abs(oldCurrentPos - item);                  smoothScrollToWithDuration(destX, 0,  duration); // скролим                 if(mOnPageChangeListener != null && curItem.position != item){                     mOnPageChangeListener.onPageSelected(item);                 }                  if (curItem.position != item && mInternalPageChangeListener != null) {                     mInternalPageChangeListener.onPageSelected(item);                 }              }         }     }       void smoothScrollToWithDuration(int x, int y, int duration){              if (getChildCount() == 0) {                 // Nothing to do.                 setScrollingCacheEnabled(false);                 return;             }             int sx = getScrollX();             int sy = getScrollY();             int dx = x - sx;             int dy = y - sy;             if (dx == 0 && dy == 0) {                 completeScroll(true);                 populate();                 setScrollState(SCROLL_STATE_IDLE);                 return;             }              setScrollingCacheEnabled(true);             setScrollState(SCROLL_STATE_SETTLING);              final int width = getClientWidth();             final int halfWidth = width / 2;             final float distanceRatio = Math.min(1f, 1.0f * Math.abs(dx) / width);              mScroller.startScroll(sx, sy, dx, dy, duration); // скролим до определенной страницы с произвольным временем             if(mScroller.isFinished()){                 setOffscreenPageLimit(DEFAULT_OFFSCREEN_PAGES); // восстанавливаем значение подэлементов             }              ViewCompat.postInvalidateOnAnimation(this);      }  

Собственно все

Хочу заметить что описание не слишком подробное но хочу улучшить, по возможности пишите что лучше объяснить

ссылка на оригинал статьи http://habrahabr.ru/post/191974/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *