2012-01-17 5 views
4

Действительно ли smoothScrollToPosition() метод для GridView работает правильно? Я нашел открытый bug report, и мой тоже работает неправильно.Smooth Scroll for GridView

setSelection() работает нормально, но я хочу гладкий эффект прокрутки.

У вас есть идеи по этой проблеме?

Если это постоянная проблема, с чего я должен начать применять хороший эффект прокрутки?

+0

Возможно, разместите какой-либо код, связанный с вашей проблемой. Не существует общеизвестных проблем с использованием плавной прокрутки в «GridView», о котором я знаю. Сообщение, которое вы связывали, похоже, жалуется на проблемы в 2.1, хотя плавная прокрутка была введена в API в 2.2 – Devunwired

+0

У меня нет ничего конкретного, у меня есть gridview с около 100 элементами .. и даже 'smoothScrollToPosition (0)' не работает правильно, но 'setSelection (0)' делает, так как он должен перемещать прокрутку в начало. Кстати, я развиваюсь на 3,2. –

+0

Я не могу ручаться за любые 3.x устройства ATM, но я знаю, что он работает в 2,3, 2,3 и 4.0 устройствах, которые у меня есть. – Devunwired

ответ

3

Хотя я не вижу проблем с кодом примера, который вы опубликовали, если вы не видите согласованных результатов в своем приложении, это не слишком сложно создать собственный контроллер прокрутки. Вот пример реализации можно использовать:

private class ScrollPositioner { 
    private static final int SCROLL_DURATION = 20; 
    private static final int DIR_UP = 1; 
    private static final int DIR_DOWN = 2; 

    int mTargetPosition = AdapterView.INVALID_POSITION; 
    int mDirection = AdapterView.INVALID_POSITION; 
    int mLastSeenPosition = AdapterView.INVALID_POSITION; 
    int mExtraScroll; 
    GridView mGrid; 

    public ScrollPositioner(GridView grid) { 
     mGrid = grid; 
     mExtraScroll = ViewConfiguration.get(mGrid.getContext()).getScaledFadingEdgeLength(); 
    } 

    Handler mHandler = new Handler(); 
    Runnable mScroller = new Runnable() { 
     public void run() { 
      int firstPos = mGrid.getFirstVisiblePosition(); 
      switch(mDirection) { 
      case DIR_UP: { 
       if (firstPos == mLastSeenPosition) { 
        // No new views, let things keep going. 
        mHandler.postDelayed(mScroller, SCROLL_DURATION); 
        return; 
       } 

       final View firstView = mGrid.getChildAt(0); 
       if (firstView == null) { 
        return; 
       } 
       final int firstViewTop = firstView.getTop(); 
       final int extraScroll = firstPos > 0 ? mExtraScroll : mGrid.getPaddingTop(); 

       mGrid.smoothScrollBy(firstViewTop - extraScroll, SCROLL_DURATION); 

       mLastSeenPosition = firstPos; 

       if (firstPos > mTargetPosition) { 
        mHandler.postDelayed(mScroller, SCROLL_DURATION); 
       } 
       break; 
      } 

      case DIR_DOWN: { 
       final int lastViewIndex = mGrid.getChildCount() - 1; 
       final int lastPos = firstPos + lastViewIndex; 

       if (lastViewIndex < 0) { 
        return; 
       } 

       if (lastPos == mLastSeenPosition) { 
        // No new views, let things keep going. 
        mHandler.postDelayed(mScroller, SCROLL_DURATION); 
        return; 
       } 

       final View lastView = mGrid.getChildAt(lastViewIndex); 
       final int lastViewHeight = lastView.getHeight(); 
       final int lastViewTop = lastView.getTop(); 
       final int lastViewPixelsShowing = mGrid.getHeight() - lastViewTop; 
       final int extraScroll = lastPos < mGrid.getAdapter().getCount() - 1 ? mExtraScroll : mGrid.getPaddingBottom(); 

       mGrid.smoothScrollBy(lastViewHeight - lastViewPixelsShowing + extraScroll, SCROLL_DURATION); 

       mLastSeenPosition = lastPos; 
       if (lastPos < mTargetPosition) { 
        mHandler.postDelayed(mScroller, SCROLL_DURATION); 
       } 
       break; 
      } 

      default: 
       break; 
      } 
     } 
    }; 

    public void scrollToPosition(int position) { 
     mTargetPosition = position; 
     mLastSeenPosition = AdapterView.INVALID_POSITION; 

     if(position < mGrid.getFirstVisiblePosition()) { 
      mDirection = DIR_UP; 
     } else if (position > mGrid.getLastVisiblePosition()) { 
      mDirection = DIR_DOWN; 
     } else { 
      return; 
     } 
     mHandler.post(mScroller); 
    } 
} 

Вот отрывок из примера вы связаны, что включает в себя, где этот новый класс, чтобы сделать скроллинг в месте реализации рамочного:

GridView g; 
boolean t= false; 
@Override 
public void onBackPressed() { 
    //Instantiate and attach the custom positioner 
    if(mPositioner == null) { 
     mPositioner = new ScrollPositioner(g); 
    } 
    //Use the custom object to scroll the view 
    mPositioner.scrollToPosition(0); 
    if(t) { 
     super.onBackPressed(); 
    } 
    else { 
     t = true; 
    } 
} 

Если вы хотите чтобы добавить функцию, в которой выбранная позиция всегда прокручивается вверх, даже когда направление прокрутки вниз, вы можете это сделать. Это не то, что реализация фреймворка рассчитана на, но вы можете выполнить его, добавив код в DIR_DOWN, чтобы продолжить прокрутку, пока первая видимая позиция не будет соответствовать цели (например, DIR_UP). Вы также должны остерегаться случая, когда прокрутка заканчивается до того, как позиция достигает вершины, поэтому вы не постоянно публикуете обработчик в случаях, когда вы никогда не получите другой результат.

НТН

+0

Это было действительно полезно. Я также рассмотрел реализацию PositionScroller в AbsListview здесь http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android /widget/AbsListView.java?av=f#3883, который является супер-классом GridView, но мне не удалось обрезать код, чтобы использовать его в моем проекте. Этот фрагмент действительно полезен. Однако, как я могу заставить прокручиваемую позицию появляться в верхней части gridview. Поскольку этот прокрутка реализации останавливается, как только элемент входит в представление, поэтому он не отображается полностью. –

+0

Я изменил свой пример на основе реализации фреймворка, так что элементы будут полностью прокручиваться на экране вместо того, чтобы останавливаться, как только они будут видны, что зажимает их за краем затухания и добавляет некоторые заметки. – Devunwired

+0

Предложенная утечка памяти класса со ссылкой на GridView –

1

Если бы тот же самый проблемный я построил простой GridView и по какой-то причине smoothScrollToPosition() не работает вообще (только подпрыгивать время от времени).

после много отладки, оказалось, что мне нужно удалить параметр android:padding из GridView.

Очень странно, я действительно не знаю, почему это так, но по крайней мере сейчас это работает.

+1

Его нужно обрезать перед вызовом 'mGrid.smoothScrollBy()'. Итак, 'mGrid.smoothScrollBy (lastViewHeight - lastViewPixelsShowing + extraScroll, SCROLL_DURATION)' становится 'mGrid.smoothScrollBy (lastViewHeight - lastViewPixelsShowing + extraScroll - grid.getListPaddingTop(), SCROLL_DURATION)' по какой-то причине нижнее дополнение не работает. – samosaris