Как добавить страницу в начало ViewPager?

О приложении
Я разрабатываю приложение calendar.Want, чтобы показать monthview с горизонтальной навигацией по навигации? Это означает, что бесконечный прокручиваемый пользователь может прокручивать вправо и влево месяц до любой даты/месяца любого года. Я нашел, что ViewPager очень полезен для достижения этого. (Я действительно не знаю, какие другие используют полные методы). И нажатием кнопки ячеек даты можно увидеть детали или события, добавленные к этой дате (я не знаю, t хотите связать с календарем устройства).

О проблеме
Я могу добавить новую страницу в конец пейджера View без каких-либо проблем. Но если пользователь переместится налево, мне нужно добавить страницу в начало моего ViewPager. . Когда я добавляю страницу в начало (индексная позиция нуля), это заменит мою текущую страницу на нулевой позиции и сможет только добавить одну страницу (новые страницы не добавляются, я не знаю почему). И после добавления страницы в нулевую позицию я не могу добавить даже добавленную страницу в конец пейджера просмотра, когда пользователь щелкает вправо и повторяет последнюю страницу. Силовое замыкание происходит с ошибкой:

java.lang.IllegalStateException: Can't change tag of fragment MyFragment{40526bb8 #2  id=0x7f070000 android:switcher:2131165184:2}: was android:switcher:2131165184:2 now android:switcher:2131165184:3

В простом предложении
Я хочу знать, как правильно добавлять страницы в начало и конец пейджера View?

код

Активность и адаптер

    public class PageViewActivity extends FragmentActivity {

    ViewPager pager;
    MyPageAdapter pageAdapter;
    ArrayList<Fragment> fragments;

    int page_num = 0;
    int current_page = 1;
    int selected_page = 1;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_page_view);

        pager = (ViewPager) findViewById(R.id.viewpager);

        fragments = getFragments();

        pageAdapter = new MyPageAdapter(getSupportFragmentManager(), pager,
                fragments);

        pager.setAdapter(pageAdapter);
        pager.setCurrentItem(2);
        pager.setOnPageChangeListener(new OnPageChangeListener() {

            @Override
            public void onPageSelected(int arg0) {

                // setting the selected page index
                selected_page = arg0;       
                //calling add page
                addPage();

            }

            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {
                // TODO Auto-generated method stub          

            }

            @Override
            public void onPageScrollStateChanged(int arg0) {
                // TODO Auto-generated method stub
            }
        });


    }

    public int addPage() {

        System.out.println("Add page called "+selected_page);
        // checking if selected page is second last and if tru adds new page 
        if (selected_page >= (pageAdapter.getCount() - 1)) {    

            System.out.println("on first condition");

            Fragment new_fragment = MyFragment.newInstance("Added to last  "+ (pageAdapter.getCount() + 1));
            //pageAdapter.fragments.add(pageAdapter.getCount(), new_fragment);
            System.out.println("pageAdapter.getCount()   :  "+pageAdapter.getCount());
            pageAdapter.add(pageAdapter.getCount(), new_fragment);
            current_page = selected_page;           
            pageAdapter.notifyDataSetChanged();
            System.out.println("New page added");
        }else if((selected_page-1)<=0){

            System.out.println("on second condition");

            Fragment new_fragment = MyFragment.newInstance("Added to begning  "+ (pageAdapter.getCount() + 1));         
            pageAdapter.add(0, new_fragment);
            current_page = selected_page;           
            //pageAdapter.notifyDataSetChanged();
        }

        return pageAdapter.getCount();


    }

    private ArrayList<Fragment> getFragments() {

        ArrayList<Fragment> fList = new ArrayList<Fragment>();

        fList.add(MyFragment.newInstance("Fragment 1"));
        fList.add(MyFragment.newInstance("Fragment 2"));
        fList.add(MyFragment.newInstance("Fragment 3"));
        fList.add(MyFragment.newInstance("Fragment 4"));
        fList.add(MyFragment.newInstance("Fragment 5"));

        return fList;
    }

    private class MyPageAdapter extends FragmentPagerAdapter {

        private ArrayList<Fragment> fragments;
        private ViewPager mPager;

        public MyPageAdapter(FragmentManager fm, ViewPager vp,
            ArrayList<Fragment> fragments) {
            super(fm);
            this.fragments = fragments;
            this.mPager = vp;


        }

        public void  add(int position,Fragment f){          
            fragments.add(position, f);
            this.notifyDataSetChanged();
        }


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

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


    }
}

Мой класс фрагментов

public class MyFragment extends Fragment {
public static final String EXTRA_MESSAGE = "EXTRA_MESSAGE";

public static final MyFragment newInstance(String message)
{
    MyFragment f = new MyFragment();
    Bundle bdl = new Bundle(1);
    bdl.putString(EXTRA_MESSAGE, message);
    f.setArguments(bdl);
    return f;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
    Bundle savedInstanceState) {

    String message = getArguments().getString(EXTRA_MESSAGE);
    View v = inflater.inflate(R.layout.myfragment_layout, container, false);
    TextView messageTextView = (TextView)v.findViewById(R.id.textView);
    messageTextView.setText(message);

    //return null;
    return v;
}


}

Ответ 1

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

  • Я устанавливаю минимальную дату и максимальную дату, которые станут пределами для дат для навигации. В моем случае я поставил большие ограничения, с 1970 по 2050 годы, чтобы быть уверенным, что я занимаю достаточно времени. Если взять более простой пример с месяцами, скажем, с 2012 по 2014 год, это означает, что у нас будет 3 года * 12 месяцев = 36 различных позиций, доступных в пейджере.

  • Когда приложение запускается, по умолчанию мой текущий фрагмент отображает текущий день, что означает для вас текущий месяц. Поэтому я создал определенную функцию в своем приложении, чтобы получить позицию внутри моей временной шкалы, чтобы получить позицию выбранной даты. Если мы снова возьмем пример выше, тогда позиция будет равна 18.

Чтобы дать вам представление, вот как я получаю текущую позицию дня в Activity:

//position in the timeline
todayPosition = Days.daysBetween(new DateTime(MIN_DATE), new DateTime(getTodayDate())).getDays();

daysBetween - это функция из библиотеки времени Joda, я использую ее для получения количества дней между минимальной датой и выбранной датой (т.е. позицией на временной шкале).

Затем в моей функции onCreate я инициализирую пейджер таким образом во время создания Activity:

pager.setCurrentItem(mApplication.getTodayPosition());

Вот адаптер, если он вас вдохновляет:

public class MyFragmentPagerAdapter extends FragmentStatePagerAdapter{

private final int todayPosition;
private MyFragment currentFragment;
private final Calendar todayDate;

/** Constructor of the class */
public MyFragmentPagerAdapter(FragmentManager fm, int today_position, Calendar today_date) {
    super(fm);
    todayPosition = today_position;
    todayDate = (Calendar) today_date.clone();
}

/** This method will be invoked when a page is requested to create */
@Override
public Fragment getItem(int arg0) {     
    currentFragment = new MyFragment();
    Bundle data = new Bundle();

    data.putInt("current_page", arg0);
    currentFragment.setArguments(data);
    return currentFragment;
}

/** Returns the number of pages */
@Override
public int getCount() {     
    return MyApplication.TOTAL_NUMBER_OF_DAYS;
}

@Override
public CharSequence getPageTitle(int position) {
    Calendar newDate = (Calendar) todayDate.clone();

    int diffDays = position - todayPosition;
    newDate.add(Calendar.DATE, diffDays);

    return MyApplication.dateTitleFormat.format(newDate.getTime());
}   
}

Я не гарантирую, что это лучшее решение, но по крайней мере оно работает.