Динамическое добавление фрагментов с обеих сторон ViewPager с использованием FragmentStatePagerAdapter

В одном из моих приложений мне нужно добавить фрагменты с обеих сторон ViewPager. Прежде всего, я получу константу из 5 каналов, а мой ViewPager покажет канал с индексом 2, т.е. мой текущий отображаемый фрагмент будет содержать данные, присутствующие в индексе 2. Таким образом, в целом мой ViewPager будет отображать центр 5 каналов при запуске, и что я достигли, просто установив текущий элемент ViewPager как 2, как это

viewPager.setCurrentItem(2);

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

feedsList.add(0, modelClassObject); // feedsList will contain all feeds and has been used by adapter to show data in fragments.
adapter.notifyDataSetChanged();

и когда я прокручиваю вправо от центрального положения, я добавляю ленту в последнюю очередь, просто вот так

feedsList.add(modelClassObject);
adapter.notifyDataSetChanged();

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

private class HorizontalPagerAdapter extends FragmentStatePagerAdapter {

    public HorizontalPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int arg0) {
        return FeedUserProfileFragment.newInstance(feedsList.get(arg0),
                arg0);
    }

    @Override
    public int getCount() {
        return feedsList.size();
    }

}

Я также использовал это

@Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

а результата нет.. :(

Так что в острой необходимости, если кто-то сделал это раньше и столкнулся с той же проблемой, пожалуйста, дайте мне знать, что я делаю неправильно. Мне нужно только добавить фрагмент по нулевому индексу моего ViewPager.


person Mukesh Rana    schedule 25.12.2014    source источник
comment
опубликуйте код FeedUserProfileFragment.newInstance(feedsList.get(arg0),arg0);   -  person mmlooloo    schedule 25.12.2014
comment
Я не думаю, что это имеет какое-либо отношение к этой проблеме   -  person Mukesh Rana    schedule 26.12.2014
comment
Я тоже сталкиваюсь с той же проблемой.   -  person Neeraj    schedule 21.11.2015


Ответы (2)


Я сталкивался с подобной проблемой раньше, и мое решение было:

  1. сначала список объявляется в самом адаптере, так что при создании экземпляра этого адаптера у меня может быть свой собственный список.
  2. изменил метод getItem(int arg0) в классе адаптера, чтобы он возвращал определенный элемент из списка в зависимости от позиции этого элемента.
  3. при создании нового фрагмента используйте метод instanceiate для его создания, а затем добавьте его к своим фрагментам.

Итак, полное решение будет:

класс адаптера:

private class HorizontalPagerAdapter extends FragmentStatePagerAdapter {

public List<Fragment> feedsList;

    public HorizontalPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        return feedsList.get(position);
    }

    @Override
    public int getCount() {
        return feedsList.size();
    }

}

и при создании адаптера:

public static YourPageAdapter adapter_obj; // make sure it's static object
adapter_obj =  new YourPageAdapter(getSupportFragmentManager());
adapter_obj.feedsList = new ArrayList<Fragment>();
// then add the list of fixed fragments to it(the 5 in the beginning)
adapter_obj.feedsList = fragments_list; // an ArrayList contains the 5 fragments

и когда хотите создать новый фрагмент:

adapter_obj.feedsList.add(0, Fragment.instantiate(mContext, ViewPager_Container_Class.class.getName(), page));
adapter_obj.notifyDataSetChanged();
person Muhammed Refaat    schedule 25.12.2014
comment
На самом деле я использую только один фрагмент, и каждый раз данные внутри этого фрагмента будут меняться. Итак, вы все еще думаете, что мне нужно взять Fragment ArrayList или вместо этого я должен иметь ArrayList данных и уведомлять этот arrayList каждый раз, когда добавляется новый канал ?? - person Mukesh Rana; 26.12.2014
comment
Я думаю, вам НЕ нужно просто добавлять данные в ArrayList и уведомлять об изменениях, я считаю, что это не будет так хорошо с фрагментацией, возьмите фрагмент ArrayList или любой другой способ, который заставит вас воссоздать фрагменты с самого начала, чтобы убедиться, что все ваши изменения будут сохранены. применяемый. - person Muhammed Refaat; 26.12.2014
comment
Я не знаю, но если бы это было проблемой, то я не смог бы добавлять каналы в конце. Значит, это тоже должно было работать. В любом случае, я тоже пробовал ваш, но вызывает у меня исключения. Я искал Исключения, но все напрасно. Итак, наконец, я решил установить адаптер каждый раз на данный момент. - person Mukesh Rana; 26.12.2014
comment
хм.. посмотрим.. жду правильного ответа. в любом случае спасибо. Ваша помощь действительно ценна .. :) - person Mukesh Rana; 26.12.2014
comment
@MuhammedRefaat stackoverflow. com/questions/40149039/ нужна помощь - person albert; 21.10.2016

FragmentStatePagerAdapter не может правильно обработать это, когда вы добавляете новый фрагмент впереди.

Обходной путь таков:

  1. Добавьте новый фрагмент в конце.
  2. Вызовите notifyDataSetChanged();
  3. Перенесите фрагмент на передний план.
  4. Вызовите notifyDataSetChanged();

Кстати, getItemPosition() должен все время возвращать правильные позиции:

public int getItemPosition(Object object)
{
    return feedsList.indexOf( object );
}

Итак, с вашим кодом это должно быть:

newFrag = Fragment.instantiate(...);
feedsList.add( newFrag );
adapter_obj.notifyDataSetChanged();

feedsList.remove( feedsList.size() - 1 );
feedsList.add( 0, newFrag );
adapter_obj.notifyDataSetChanged();

Я предполагаю, что реализация FragmentStatePagerAdapter не предполагает одновременного добавления нового фрагмента и изменения позиции.

person Vincent    schedule 21.10.2016
comment
Можете ли вы объяснить, почему FragmentPagerAdpter не может обрабатывать объекты, добавленные на передний план? - person Vivek Av; 16.02.2018