lolyoshi
lolyoshi

Reputation: 1546

How to make unlimited pager using ViewPager in Android

I want to display unlimited viewpager in my calendar when I slide the month view. How can I do that? I think I need 3 fragments to do that. However, I don't know how to update the month (fragment) when I swipe Left or right. I attached my code below. I give question marks where I have no idea to code. This is my project: https://github.com/lolyoshi/CalendarWidget

Any help is appreciated.

InfinitedPagerAdapter.java

public class InfinitePagerAdapter extends FragmentPagerAdapter{

    CalendarView[] fragList;  
    int fragNumber = 3;

    public InfinitePagerAdapter(FragmentManager fm, CalendarView[] fragList) {
        super(fm);
        this.fragList = fragList;
    }

    @Override
    public int getItemPosition(Object object) {
        // TODO Auto-generated method stub
        return POSITION_NONE;
    }

    @Override
    public Fragment getItem(int position) {
        return fragList[position];      
    }

    @Override
    public int getCount() {
        return fragNumber;
    }

    public void setCalendar(????) {
          //Need to update 3 fragments
           ??????????????????????
    }

    @Override
    public boolean isViewFromObject(View arg0, Object arg1) {
        // TODO Auto-generated method stub
        return false;
    }
}

CalendarWidget.java

public class CalendarWidget extends FragmentActivity {
    ViewPager monthPage;
    private static final int PAGE_MIDDLE = 1;
    private int mSelectedPageIndex = 1;
    public Calendar curMonth;
    InfinitePagerAdapter monthPageAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.calendar_layout);

        CalendarView[] fragList = new CalendarView[3];
        curMonth = Calendar.getInstance();
        Calendar prevMonth, nextMonth;
        prevMonth = (Calendar) curMonth.clone();
        nextMonth = (Calendar) curMonth.clone();
        prevMonth.set(Calendar.MONTH, prevMonth.get(Calendar.MONTH) - 1);
        nextMonth.set(Calendar.MONTH, nextMonth.get(Calendar.MONTH) + 1);
        fragList[0] = CalendarView.newInstance(prevMonth);
        fragList[1] = CalendarView.newInstance(curMonth);
        fragList[2] = CalendarView.newInstance(nextMonth);

        monthPage = (ViewPager)findViewById(R.id.pager);
        monthPageAdapter = new InfinitePagerAdapter(getSupportFragmentManager(), fragList);
        monthPage.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

            @Override
            public void onPageScrollStateChanged(int arg0) {
                // TODO Auto-generated method stub
                 if (mSelectedPageIndex < PAGE_MIDDLE) {
                     curMonth.add(Calendar.MONTH, -1);
                    } else if (mSelectedPageIndex > PAGE_MIDDLE) {
                        curMonth.add(Calendar.MONTH, 1);    
                    }
                                        //Need to update 3 fragments
                    monthPageAdapter.setCalendar(????);
                        monthPage.setCurrentItem(1, false);
            }

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

            }

            @Override
            public void onPageSelected(int arg0) {
                // TODO Auto-generated method stub
                mSelectedPageIndex = arg0;
            }});
        monthPage.setAdapter(monthPageAdapter);
        monthPage.setCurrentItem(1, false);
    }    
}

CalendarView.java

public class CalendarView extends Fragment{
    protected static Calendar calendar;
    protected final Calendar itemMonth;
    private CalendarAdapter calendarAdapter;
    private LinearLayout calendarLayout;
    public ArrayList<String> items;
    ArrayList<String> event;
    ArrayList<String> desc;
    public Handler handler;
    private int mMonth, mYear;

    private static final int PAGE_LEFT = 0;
    private static final int PAGE_MIDDLE = 1;
    private static final int PAGE_RIGHT = 2;

    static CalendarView newInstance(?????) {
        //What can I put in this function?
        return f;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        calendarLayout = (LinearLayout)inflater.inflate(R.layout.calendar_layout, container, false);
        final GridView calendarDayGrid = (GridView)calendarLayout.findViewById(R.id.calendar_days_grid);
        calendarDayGrid.setAdapter(new ArrayAdapter<String>(getActivity(), R.layout.day_cell, getResources().getStringArray(R.array.days_array)));
        final GridView calendarGrid = (GridView)calendarLayout.findViewById(R.id.calendar_grid);
        calendarGrid.setOnTouchListener(new OnTouchListener(){
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if(event.getAction() == MotionEvent.ACTION_MOVE){
                    return true;
                }
                return false;
            }

        });
        calendarGrid.setOnItemClickListener(new DayItemClickListener());
        DisplayMetrics displaymetrics = new DisplayMetrics();
        getActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        int height = displaymetrics.heightPixels;
        int width = displaymetrics.widthPixels;
        float gridHeight = height*3/4 - 3*(convertDpToPixels(50, getActivity())); //fix the height of table of days in week = 25dp
        calendarAdapter = new CalendarAdapter(getActivity(), calendar, gridHeight);
        updateCurrentMonth();         
        calendarGrid.setAdapter(calendarAdapter);
        return calendarLayout;
    }

    public CalendarView() {
        calendar = Calendar.getInstance();
        itemMonth = (Calendar) calendar.clone();
    }


    protected void updateCurrentMonth() {
        calendarAdapter.refreshDays();
        //handler.post(calendarUpdater);
        TextView month = (TextView)calendarLayout.findViewById(R.id.month_title);        
        month.setTextColor(Color.BLACK);
        int monthID = calendar.get(Calendar.MONTH);
        int[] monthIds = {R.string.january,R.string.february,R.string.march,R.string.april,R.string.may,R.string.june,
                R.string.july,R.string.august,R.string.september,R.string.october,R.string.november,R.string.december};
        month.setText(monthIds[monthID]);
        String tmp = (String) month.getText();
        month.setText(tmp + " " + calendar.get(Calendar.YEAR));
    }

    protected final void onNextMonth() {
        if (calendar.get(Calendar.MONTH) == Calendar.DECEMBER) {
            calendar.set((calendar.get(Calendar.YEAR) + 1), Calendar.JANUARY, 1);
        } else {
            calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) + 1);
        }
        updateCurrentMonth(calendar);
    }

    protected final void onPreviousMonth() {
        if (calendar.get(Calendar.MONTH) == Calendar.JANUARY) {
            calendar.set((calendar.get(Calendar.YEAR) - 1), Calendar.DECEMBER, 1);
        } else {
            calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH)-1);
        }
        updateCurrentMonth(calendar);
    }

    public static float convertDpToPixels(float dp,Context context){
        Resources resources = context.getResources();
        DisplayMetrics metrics = resources.getDisplayMetrics();
        float px = dp * (metrics.densityDpi/160f);
        return px;
    }

    public static float convertPixelsToDp(float px,Context context){
        Resources resources = context.getResources();
        DisplayMetrics metrics = resources.getDisplayMetrics();
        float dp = px / (metrics.densityDpi / 160f);
        return dp;   
    }

    private final class DayItemClickListener implements OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            final TextView dayView = (TextView)view.findViewById(R.id.date_in_cell);
            final CharSequence text = dayView.getText();
            if (text != null && !"".equals(text)) {
                calendarAdapter.setSelected(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), Integer.valueOf(String.valueOf(text)));
            }
        }       
    }
}

Upvotes: 4

Views: 6797

Answers (1)

Amulya Khare
Amulya Khare

Reputation: 7708

The reason why your month don't update when you swipe is because you have declared the protected static Calendar calendar; static. Once you remove the static, all three pages show different months.

Keep your calendar view just as it is on github, except this change:

static CalendarView newInstance(Calendar a) {
    CalendarView f = new CalendarView(a);
    return f;
}

public CalendarView(Calendar cal) {
    calendar = cal;
}

Your adapter will be as simple as:

public class InfinitePagerAdapter extends FragmentPagerAdapter{

    CalendarView[] fragList;  

    public InfinitePagerAdapter(FragmentManager fm, CalendarView[] fragList) {
        super(fm);
        this.fragList = fragList;
    }

    @Override
    public Fragment getItem(int position) {
        return fragList[position];
    }

    @Override
    public int getCount() {
        return fragList.length;
    }
}

Finally in your Calendar widget modify as below:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_calendar_widget);

        final CalendarView[] fragList = new CalendarView[3];
        curMonth = Calendar.getInstance();
        Calendar prevMonth, nextMonth;
        prevMonth = (Calendar) curMonth.clone();
        nextMonth = (Calendar) curMonth.clone();
        prevMonth.set(Calendar.MONTH, prevMonth.get(Calendar.MONTH) - 1);
        nextMonth.set(Calendar.MONTH, nextMonth.get(Calendar.MONTH) + 1);
        fragList[0] = CalendarView.newInstance(prevMonth);
        fragList[1] = CalendarView.newInstance(curMonth);
        fragList[2] = CalendarView.newInstance(nextMonth);

        monthPage = (ViewPager) findViewById(R.id.pager);
        monthPageAdapter = new InfinitePagerAdapter(getSupportFragmentManager(), fragList);
        monthPage.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

            @Override
            public void onPageScrollStateChanged(int arg0) {
                // TODO Auto-generated method stub
                if (arg0 == ViewPager.SCROLL_STATE_IDLE) {
                    if (mSelectedPageIndex < PAGE_MIDDLE) {
                        fragList[0].onPreviousMonth();
                        fragList[1].onPreviousMonth();
                        fragList[2].onPreviousMonth();
                    } else if (mSelectedPageIndex > PAGE_MIDDLE) {
                        fragList[0].onNextMonth();
                        fragList[1].onNextMonth();
                        fragList[2].onNextMonth();
                    }
                    monthPage.setCurrentItem(1, false);
                }
            }

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

            }

            @Override
            public void onPageSelected(int arg0) {
                // TODO Auto-generated method stub
                mSelectedPageIndex = arg0;
            }
        });
        monthPage.setAdapter(monthPageAdapter);
        monthPage.setCurrentItem(1, false);
    }

That is all you need to do. Everything should work as desired.

Note: Despite everything works, cloning and passing around calendar objects may not be the best thing to do. Calendar objects are expensive. You should pass around Time if possible. Take some motivation from here

Upvotes: 5

Related Questions