11

关于我的应用程序
我正在开发一个日历应用程序。想要通过水平滑动导航显示月视图吗?这意味着无限滚动用户可以按月左右滚动到任何年份的任何日期/月份。我发现 ViewPager 非常有用来实现这一点。(我真的不知道其他使用完整的方法是什么)。通过单击日期单元格,用户可以看到添加到该日期的详细信息或事件(我不知道)不想与设备日历链接)。

关于这个问题
,我可以毫无问题地将新页面添加到 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 pager 的开头和结尾的正确方法是什么?

代码

活动和适配器

    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;
}


}
4

1 回答 1

3

我将在这里解释我的做法,我添加设置相同的东西,除了我需要在几天而不是几个月之间左右滑动:

  1. 我设置了一个最小日期和一个最大日期,它们将成为导航日期的限制。就我而言,我设定了很大的限制,从 1970 年到 2050 年,以确保我能处理足够的时间线。如果我们举一个更简单的月份示例,比如 2012 年到 2014 年,这意味着我们将有 3 年 * 12 个月 = 36 个不同的位置可用在寻呼机中。

  2. 当应用程序启动时,默认情况下,我的当前片段显示当前日期,对您来说意味着当前月份。所以我在我的应用程序上创建了一个特定的函数来获取我的时间轴内的位置,以获取其中所选日期的位置。如果我们再看上面的例子,那么这个位置就是 18。

为了给你一个想法,这里是我如何获得我的当前位置Activity

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

daysBetween是 Joda Time 库中的一个函数,我用它来获取最小日期和所选日期之间的天数(即时间轴中的位置)。

然后在我的onCreate函数中,我在创建活动期间以这种方式初始化寻呼机:

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());
}   
}

我不保证这是最好的解决方案,但至少它是有效的。

于 2013-06-07T13:52:25.740 回答