Раздел Indexer Overlay не обновляется по мере изменения данных адаптера

Я внедрил Index Indexer для класса адаптера, который расширяет BaseAdapter. Теперь для первого запуска Index Indexer показывает наложение правильно. Но когда содержимое списка обновляется, раздел Overlay не обновляется и дает ArrayOutOfBoundException. Для одного исправить то, что я сделал, я сделал listview.setFastScrollEnabled(false); обновить содержимое адаптера; а затем listview.setFastScrollEnabled(true); Теперь случается, что оверлей обновляется, но Overlay приближается к левой верхней части списка. Как я могу это исправить.

Ответ 1

небольшое обходное решение, предложенное lee.wilmot,

private void jiggleGrid() {

          int newWidth = flag( FLAG_THUMB_PLUS ) ?
FrameLayout.LayoutParams.FILL_PARENT :
                  grid.getWidth() - 1;

          FrameLayout.LayoutParams l = new FrameLayout.LayoutParams(
                          newWidth,
                          FrameLayout.LayoutParams.FILL_PARENT
          );

          grid.setLayoutParams( l );

          toggleFlag( FLAG_THUMB_PLUS );
  }
Флаг

и toggleFlag - это некоторые функции.

Вызвать этот метод после установки setFastScrollEnabled(true);. Это сработало для меня....

Ответ 2

Думаю, что я поделился бы готовой версией описанного выше решения для ListActivity:

private boolean FLAG_THUMB_PLUS = false;
private void jiggleWidth() {

    ListView view = getListView();
    if (view.getWidth() <= 0)
        return;

    int newWidth = FLAG_THUMB_PLUS ? view.getWidth() - 1 : view.getWidth() + 1;
    ViewGroup.LayoutParams params = view.getLayoutParams();
    params.width = newWidth;
    view.setLayoutParams( params );

    FLAG_THUMB_PLUS = !FLAG_THUMB_PLUS;
}

Работает для меня.

Ответ 3

Чтобы он работал во всех случаях (особенно с макетом FILL_PARENT и изменением ориентации), вместо использования ListView напрямую используйте этот класс и вызывайте invalidateSectionIndexer() после изменения вашего адаптера.

class MyListView extends ListView {
    public MyListView(Context context) {
        super(context);
    }

    public void invalidateSectionIndexer() {
        // 1. this invalidates the Section Indexer
        super.setFastScrollEnabled(false);
        // Your adapter might be wrapped, e.g. when adding headers/footers.
        ListAdapter adapter = getAdapter();
        BaseAdapter baseAdapter = (adapter instanceof WrapperListAdapter) ?
                (BaseAdapter) ((WrapperListAdapter) adapter).getWrappedAdapter() :
                (BaseAdapter) adapter;
        baseAdapter.notifyDataSetChanged();
        super.setFastScrollEnabled(true);

        // 2. This fixes the android bug of section overlay not positioned correctly.
        int width = getWidth();
        int height = getHeight();
        super.onSizeChanged(width, height, width, height);
    }
}

Ответ 4

Выше решения в порядке, за исключением случая, когда ширина установлена ​​на FILL_PARENT. Чтобы заставить их работать для этого случая, вы должны переопределить onSizeChanged как это

@Override
protected void onSizeChanged (int w, int h, int oldw, int oldh)
{
    super.onSizeChanged( w , h , oldw , oldh );
    if ( mInstance.getLayoutParams().width != FrameLayout.LayoutParams.FILL_PARENT )
    {
        mInstance.post( new Runnable()
        {   
            @Override
            public void run()
            {
                mInstance.setLayoutParams( new FrameLayout.LayoutParams( FrameLayout.LayoutParams.FILL_PARENT , FrameLayout.LayoutParams.FILL_PARENT ) );   
            }
        });
    }
}

При этом размер модификации будет одобрен после изменения ориентации экрана.

Ответ 5

У меня возникла аналогичная проблема, используя ResourceCursorAdapter. Раздел indexer не обновлялся после того, как был установлен новый адаптер для списка или метод swapCursor() для обновления курсора. Я пробовал все решения, размещенные на StackOverflow, без каких-либо успехов. Только работающий обходной путь, который я нашел, заключается в том, что вам нужно отсоединить/присоединить фрагмент, который вы хотите обновить (вам нужно запустить метод фрагмента onCreateView(), где вы создаете свой пользовательский интерфейс) после обновления моего курсора ( а не CursorAdapter.. вам нужно обновить/установить адаптер в onCreateView()). Это сработало для меня. Вот код, который я использую для повторного прикрепления фрагмента.

fragmentManager.beginTransaction().detach(frag).attach(frag).commitAllowingStateLoss();

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