自定义日历 ViewPager FragmentStatePagerAdapter 自定义View
2014-10-23 21:39
246 查看
一直想给最近在做的笔记本加一个日历查找的功能,但是google源生的calendarView似乎只能上下滑动,而且不支持在日历上标注文字。
本人才浅,面对谷歌日历源码无从下手,于是想自己开发一个可以左右滑动,并且支持标注当日记录数的日历。
实现效果如图
实现思路:
android.support.v4.view.ViewPager可以提供一个左右滑动的效果,实现其适配器android.support.v4.app.FragmentStatePagerAdapter,其中每个日历界面是它的一个Fragment,在这个Fragment中的onCreateView加载自定义的日历View。
FragmentStatePagerAdapter这个适配器可以不缓存每个自定义View的视图,当左右滑动后,前一个Fragment会被销毁,因此保证大量滑动不会造成太多内存浪费。
1 自定义日历View
2 将自定义的日历View装入Fragment,以供Viewpager的适配器调用
3 实现FragmentStatePagerAdapter
简单定义适配器,算出总共有多少个月,每个Fragment就是上面写的,并且实现它的回调接受日期选中事件。\
上面的代码有bug,Fragment最好不要加带参数的构造方法,如
另外
最好写成这样
@Override
public void onAttach(Activity mActivity) {
super.onAttach(mActivity);
this.mActivity = mActivity;
mCallBack = (CallBack)mActivity;
}
另外想要向fragment共享复杂类型对象,可以通过继承Application的方法,在Application对象中提供对象的接口。不要把对象加在Fragment的构造函数里,因为程序最小化后可能调用无参的默认的构造行数。
如果你觉得平移的滑动方式不够炫酷可以使用JazzyViewPager满足你的需求,封装了多种左右滑动的切换动画。
如果滑动觉得卡顿,可以像我一样自定义Viewpager,在onTouchEvent作判断,超过一段距离就返回true,把touch事件消耗掉,而不是传递给子view。
本人才浅,面对谷歌日历源码无从下手,于是想自己开发一个可以左右滑动,并且支持标注当日记录数的日历。
实现效果如图
实现思路:
android.support.v4.view.ViewPager可以提供一个左右滑动的效果,实现其适配器android.support.v4.app.FragmentStatePagerAdapter,其中每个日历界面是它的一个Fragment,在这个Fragment中的onCreateView加载自定义的日历View。
FragmentStatePagerAdapter这个适配器可以不缓存每个自定义View的视图,当左右滑动后,前一个Fragment会被销毁,因此保证大量滑动不会造成太多内存浪费。
1 自定义日历View
public class NoteCalendar2 extends View { private int nums_of_row = 6; private int nums_of_columns = 7; private final static float STARTX = 0; private final static float STARTY = 0; private float gridWidth; private float gridHeight; private float titleGridHeight; private float titleGridWidth; private int backgroundColor = Color.TRANSPARENT; private boolean showGridRowLine = false; private boolean showGridColumnLine = false; private int currentMonthEndX; private int currentMonthEndY; private final int currentMonthTextColor = Color.DKGRAY; private final int otherMonthTextColor = Color.LTGRAY; private final int countColor = Color.BLACK; private final int selectedCellBG = Color.RED; private final int currentMonthTextSize = 50; private final int otherMonthTextSize = 43; private boolean touchable = true; public boolean isTouchable() { return touchable; } public void setTouchable(boolean touchable) { this.touchable = touchable; } private NoteDataBaseManager mNoteDataBaseManager; // List<Cell> monthDates; Cell[][] currentMonthArray; int[] record_count; // curent date private int Year; // actual year public void setYear(int year) { Year = year; } public void setMonth(int month) { Month = month; } public void setDayOfMonth(int dayOfMonth) { DayOfMonth = dayOfMonth; } private int Month; // actual month private int DayOfMonth; // actual day private int selectedYear; public int getSelectedYear() { return selectedYear; } public int getSelectedMonth() { return selectedMonth; } public int getSelectedDay() { return selectedDay; } private int selectedMonth; private int selectedDay; private int todayYear; private int todayMonth; private int todayDay; public int SLIDING_LENGTH = 300; Paint paint; int row1, row2, row3, column1, column2, column3; boolean notOutOfRange = true; float begin, end; ChangeDateListener mChangeDateListener; public void setSelectedDay(int year, int month, int dayOfMonth) { this.selectedYear = year; this.selectedMonth = month; this.selectedDay = dayOfMonth; if (mChangeDateListener != null) { mChangeDateListener.onChangeSelectedDate(selectedYear, selectedMonth, selectedDay); } } public NoteCalendar2(Context context) { super(context); paint = new Paint(); setCurrentDate(); initNoteDataBaseManager(context); } private void initNoteDataBaseManager(Context context) { mNoteDataBaseManager = NoteApplication.getDbManager(); } private void setCurrentDate() { Calendar cal = Calendar.getInstance(); this.Year = cal.get(Calendar.YEAR); this.Month = cal.get(Calendar.MONTH) + 1; this.DayOfMonth = cal.get(Calendar.DAY_OF_MONTH); this.todayYear = this.Year; this.todayMonth = this.Month; this.todayDay = this.DayOfMonth; } public void setOnChangeDateListener(ChangeDateListener c) { mChangeDateListener = c; } public NoteCalendar2(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NoteCalendar); backgroundColor = a.getColor(R.styleable.NoteCalendar_backgroundColor, backgroundColor); a.recycle(); paint = new Paint(); setCurrentDate(); initNoteDataBaseManager(context); } @Override public void onDraw(Canvas canvas) { // Log.d("screen", "view width = " + getWidth()); // Log.d("screen", "view width = " + getHeight()); caculateCurrentMonthDates(); caculateOtherMonthDates(); gridHeight = this.getHeight() / (this.nums_of_row + 0.5F); gridWidth = this.getWidth() / this.nums_of_columns; titleGridWidth = gridWidth; titleGridHeight = (this.getHeight() / (this.nums_of_row + 0.5F)) * 0.5F; drawCalendarBG(canvas); drawCalendarEdge(canvas); drawWeeks(canvas); drawRowsAndColumns(canvas); drawDayOfMonth(canvas); super.onDraw(canvas); } public void drawDayOfMonth(Canvas canvas) { for (int i = 0; i < nums_of_row; i++) { for (int j = 0; j < nums_of_columns; j++) { if (currentMonthArray[i][j] != null) { if (currentMonthArray[i][j].isCurrentDayOfMonth == true) { if (currentMonthArray[i][j].year == this.todayYear && currentMonthArray[i][j].month == this.todayMonth && currentMonthArray[i][j].dayOfMonth == this.todayDay) { drawCellBG(canvas, i, j, Color.parseColor("#44FFFFFF") , true); if (selectedYear == todayYear && selectedMonth == todayMonth && selectedDay == todayDay) { paint.reset(); paint.setStyle(Style.FILL); paint.setColor(selectedCellBG); paint.setAntiAlias(true); paint.setAlpha(90); paint.setAntiAlias(true); canvas.drawCircle( j * gridWidth + 5 + (gridWidth - 10) / 2, ((0.5F * gridHeight + (i + 1) * gridHeight - 5) - (titleGridHeight + 5 + i * gridHeight)) / 2 + titleGridHeight + 5 + i * gridHeight, (gridHeight - 20) / 2, paint); } paint.reset(); paint.setTextSize(currentMonthTextSize); paint.setTextAlign(Align.CENTER); paint.setColor(currentMonthTextColor); paint.setAntiAlias(true); paint.setTypeface(Typeface.DEFAULT_BOLD); canvas.drawText( String.valueOf(currentMonthArray[i][j].dayOfMonth), STARTX + j * titleGridWidth + 0.5F * gridWidth, STARTY + titleGridHeight + (i + 0.65F) * gridHeight, paint); } else if (currentMonthArray[i][j].year == this.selectedYear && currentMonthArray[i][j].month == this.selectedMonth && currentMonthArray[i][j].dayOfMonth == this.selectedDay) { drawCellBG(canvas, i, j, selectedCellBG, false); paint.reset(); paint.setTextSize(currentMonthTextSize); paint.setTextAlign(Align.CENTER); paint.setColor(Color.WHITE); paint.setAntiAlias(true); paint.setTypeface(Typeface.DEFAULT_BOLD); canvas.drawText( String.valueOf(currentMonthArray[i][j].dayOfMonth), STARTX + j * titleGridWidth + 0.5F * gridWidth, STARTY + titleGridHeight + (i + 0.65F) * gridHeight, paint); } else { // drawCellBG(canvas, i, j, Color.argb(200, 200, // 220, 230)); paint.reset(); paint.setTextSize(currentMonthTextSize); paint.setTextAlign(Align.CENTER); paint.setColor(currentMonthTextColor); paint.setAntiAlias(true); paint.setTypeface(Typeface.DEFAULT_BOLD); canvas.drawText( String.valueOf(currentMonthArray[i][j].dayOfMonth), STARTX + j * titleGridWidth + 0.5F * gridWidth, STARTY + titleGridHeight + (i + 0.65F) * gridHeight, paint); } if (currentMonthArray[i][j].record_count != 0) { paint.reset(); paint.setTextSize(34); paint.setTextAlign(Align.CENTER); paint.setColor(countColor); paint.setTypeface(Typeface.DEFAULT_BOLD); paint.setAntiAlias(true); canvas.drawText( String.valueOf(currentMonthArray[i][j].record_count), STARTX + j * titleGridWidth + 0.75F * gridWidth, STARTY + titleGridHeight + (i + 0.3F) * gridHeight, paint); } } else { paint.reset(); paint.setTextSize(otherMonthTextSize); paint.setTextAlign(Align.CENTER); paint.setColor(otherMonthTextColor); paint.setAntiAlias(true); paint.setTypeface(Typeface.DEFAULT_BOLD); canvas.drawText(String .valueOf(currentMonthArray[i][j].dayOfMonth), STARTX + j * titleGridWidth + 0.5F * gridWidth, STARTY + titleGridHeight + (i + 0.65F) * gridHeight, paint); } } } } } public void drawCellBG(Canvas canvas, int x, int y, int color, boolean today) { paint.reset(); paint.setStyle(Style.FILL); paint.setColor(color); paint.setAntiAlias(true); paint.setAlpha(100); if (today) { // canvas.drawRect(y * gridWidth + 5, titleGridHeight + 5 + x // * gridHeight, (y + 1) * gridWidth - 5, 0.5F * gridHeight // + (x + 1) * gridHeight - 5, paint); canvas.drawCircle( y * gridWidth + 5 + (gridWidth - 10) / 2, ((0.5F * gridHeight + (x + 1) * gridHeight - 5) - (titleGridHeight + 5 + x * gridHeight)) / 2 + titleGridHeight + 5 + x * gridHeight, (gridHeight - 10) / 2, paint); } else { canvas.drawCircle( y * gridWidth + 5 + (gridWidth - 10) / 2, ((0.5F * gridHeight + (x + 1) * gridHeight - 5) - (titleGridHeight + 5 + x * gridHeight)) / 2 + titleGridHeight + 5 + x * gridHeight, (gridHeight - 10) / 2, paint); } } public void drawWeeks(Canvas canvas) { paint.reset(); paint.setStrokeWidth(1); canvas.drawLine(0, STARTY + titleGridHeight, this.nums_of_columns * titleGridWidth, STARTY + titleGridHeight, paint); String[] weekTitles = this.getContext().getResources() .getStringArray(R.array.week_titles); paint.reset(); paint.setTextSize(45); paint.setColor(Color.DKGRAY); paint.setTypeface(Typeface.DEFAULT_BOLD); paint.setTextAlign(Align.CENTER); for (int i = 0; i < this.nums_of_columns; i++) { canvas.drawText(weekTitles[i], STARTX + i * titleGridWidth + 0.5F * titleGridWidth, (STARTY + titleGridHeight) * 0.7F, paint); } } public void drawRowsAndColumns(Canvas canvas) { paint.reset(); paint.setStrokeWidth(2); paint.setColor(Color.DKGRAY); // drawRows if (showGridRowLine) { for (int i = 0; i < this.nums_of_columns - 2; i++) { canvas.drawLine(0, STARTY + titleGridHeight + (i + 1) * gridHeight, this.nums_of_columns * gridWidth, STARTY + titleGridHeight + (i + 1) * gridHeight, paint); } } if (showGridColumnLine) { for (int h = 0; h < this.nums_of_columns - 1; h++) { canvas.drawLine(STARTX + (h + 1) * gridWidth, STARTY, STARTX + (h + 1) * gridWidth, STARTY + (this.nums_of_row + 0.5F) * gridHeight, paint); } } // paint.setColor(Color.BLACK); // canvas.drawLine(0, STARTY, this.nums_of_columns * gridWidth, STARTY, // paint); } public void drawCalendarEdge(Canvas canvas) { paint.reset(); paint.setColor(Color.DKGRAY); paint.setStrokeWidth(3); paint.setStyle(Style.STROKE); canvas.drawRect(0, 0, this.getWidth(), this.getHeight(), paint); } public void drawCalendarBG(Canvas canvas) { paint.reset(); paint.setStyle(Style.FILL); paint.setColor(backgroundColor); canvas.drawRect(0, 0, this.getWidth(), this.getHeight(), paint); } public int getDayOfWeek(int year, int month, int dayOfMonth) { Date date = new Date(year - 1900, month - 1, dayOfMonth); Calendar calendar = Calendar.getInstance(); calendar.setTime(date); int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1; if (dayOfWeek == 0) { return 7; } return dayOfWeek; } public int getDaysOfMonth(int year, int month) { Calendar test = Calendar.getInstance(); test.set(Calendar.YEAR, year); test.set(Calendar.MONTH, month - 1); int totalDay = test.getActualMaximum(Calendar.DAY_OF_MONTH); return totalDay; } public void caculateOtherMonthDates() { // caculate previous month Calendar previous = Calendar.getInstance(); int previousMonth = 0; int previousYear = 0; if (this.Month == 1) { previousMonth = 12; previousYear = this.Year - 1; } else { previousMonth = this.Month - 1; previousYear = this.Year; } previous.set(Calendar.YEAR, previousYear); // actual year previous.set(Calendar.MONTH, previousMonth - 1); // actual month - 1 int dayOfPreviousMonth = getDaysOfMonth(previousYear, previousMonth) + 1; int dayOfWeekOfFirstDayOfMonth = getDayOfWeek(this.Year, this.Month, 1); for (int i = dayOfWeekOfFirstDayOfMonth - 2; i >= 0; i--) { dayOfPreviousMonth--; Cell cell = new Cell(); cell.year = previousYear; cell.month = previousMonth; cell.dayOfMonth = dayOfPreviousMonth; currentMonthArray[0][i] = cell; } // caculate next month int dayOfNextMonth = 0; int nextMonth = 0; int nextYear = 0; if (this.Month == 12) { nextMonth = 1; nextYear = this.Year + 1; } else { nextMonth = this.Month + 1; nextYear = this.Year; } boolean begin = false; if (this.currentMonthEndX == 5) { for (int j = this.currentMonthEndY; j < this.currentMonthArray[5].length; j++) { dayOfNextMonth++; Cell cell = new Cell(); cell.year = nextYear; cell.month = nextMonth; cell.dayOfMonth = dayOfNextMonth; currentMonthArray[5][j] = cell; } } else { for (int i = this.currentMonthEndX; i < this.currentMonthArray.length; i++) { for (int j = 0; j < this.currentMonthArray[i].length; j++) { if (i < this.currentMonthArray.length - 1 && j == this.currentMonthEndY) { dayOfNextMonth++; Cell cell = new Cell(); cell.year = nextYear; cell.month = nextMonth; cell.dayOfMonth = dayOfNextMonth; currentMonthArray[i][j] = cell; begin = true; } else { if (begin) { dayOfNextMonth++; Cell cell = new Cell(); cell.year = nextYear; cell.month = nextMonth; cell.dayOfMonth = dayOfNextMonth; currentMonthArray[i][j] = cell; } } } } } } public void caculateCurrentMonthDates() { int dayOfWeekOfFirstDayOfMonth = getDayOfWeek(this.Year, this.Month, 1); int totalDaysOfMonth = getDaysOfMonth(this.Year, this.Month); int dayOfMonth = 0; // Log.d("time", "dayOfWeek = " + dayOfWeekOfFirstDayOfMonth); // Log.d("time", "getDaysOfMonth = " + totalDaysOfMonth); record_count = mNoteDataBaseManager.getCurrentMonthRecordCount( this.Year, this.Month, totalDaysOfMonth); // for(int i = 0 ; i<record_count.length;i++){ // Log.d("db","["+(i+1)+"] = "+record_count[i]); // } boolean begin = false; // Log.d("time", "start"); currentMonthArray = new Cell[nums_of_row][nums_of_columns]; // monthDates = new ArrayList<Cell>(); boolean flag = true; for (int i = 0; i < this.currentMonthArray.length; i++) { if (!flag) { break; } for (int j = 0; j < this.currentMonthArray[i].length; j++) { if (i == 0 && (j + 1) == dayOfWeekOfFirstDayOfMonth) { dayOfMonth = dayOfMonth + 1; Cell cell = new Cell(); cell.year = this.Year; cell.month = this.Month; cell.dayOfMonth = dayOfMonth; cell.isCurrentDayOfMonth = true; cell.record_count = record_count[(dayOfMonth - 1)]; currentMonthArray[i][j] = cell; begin = true; } else { if (begin) { if (dayOfMonth < totalDaysOfMonth) { dayOfMonth = dayOfMonth + 1; Cell cell = new Cell(); cell.year = this.Year; cell.month = this.Month; cell.dayOfMonth = dayOfMonth; cell.isCurrentDayOfMonth = true; cell.record_count = record_count[(dayOfMonth - 1)]; currentMonthArray[i][j] = cell; } else { currentMonthEndX = i; currentMonthEndY = j; flag = false; break; } } } } } for (int i = 0; i < this.currentMonthArray.length; i++) { for (int j = 0; j < this.currentMonthArray[i].length; j++) { // Log.d("time", "currentMonthArray[" + (i + 1) + "][" + (j + 1) // + "] = " + currentMonthArray[i][j]); } } // Log.d("time", "finish"); } private class Cell { public int year; public int month; public int dayOfMonth; boolean isCurrentDayOfMonth; public int record_count; } private void touchToChangeDate(float x, float y) { int row = (int) ((y - this.titleGridHeight) / this.gridHeight); int column = (int) (x / this.gridWidth); android.util.Log.d("touch", "row = " + row); android.util.Log.d("touch", "column = " + column); } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { begin = event.getX(); android.util.Log.d("touch", "begin = " + begin); if (event.getY() > this.titleGridHeight) { row1 = (int) ((event.getY() - this.titleGridHeight) / this.gridHeight); column1 = (int) (event.getX() / this.gridWidth); } } if (event.getAction() == MotionEvent.ACTION_MOVE) { row2 = (int) ((event.getY() - this.titleGridHeight) / this.gridHeight); column2 = (int) (event.getX() / this.gridWidth); if (row2 != row1 || column2 != column1) { this.notOutOfRange = false; } } if (event.getAction() == MotionEvent.ACTION_UP) { this.setBackgroundResource(R.color.transparent); if (event.getY() > this.titleGridHeight && touchable) { row3 = (int) ((event.getY() - this.titleGridHeight) / this.gridHeight); column3 = (int) (event.getX() / this.gridWidth); // android.util.Log.d("touch","row2 = "+(row2+1)); // android.util.Log.d("touch","column2 = "+(column2+1)); if (notOutOfRange && row1 == row3 && column1 == column3) { // android.util.Log.d("touch", "change Date!"); Log.d("test", "calendar onPageScrollStateChanged state = " + Config.contentPagerScrollState); if (Config.contentPagerScrollState == 0) { changeDate(row3, column3); } } } notOutOfRange = true; float end = event.getX(); } return true; } private void changeDate(int row, int column) { Cell cell = this.currentMonthArray[row][column]; setSelectedDay(cell.year, cell.month, cell.dayOfMonth); this.invalidate(); } public int getYear() { return this.Year; } public int getMonth() { return this.Month; } public int getDayOfMonth() { return this.DayOfMonth; } public interface ChangeDateListener { abstract void onChangeSelectedDate(int year, int month, int day); // abstract void onChangeMonth(); } public void setYearAndMonth(int year, int month) { this.Year = year; this.Month = month; this.invalidate(); } }实现该view绘制完全用的是Canvas的draw方法。考虑到交互方面要有点击选中的效果,在onTouchEvent函数监听点击的位置并算出点击的日期。个人觉得实现的有点不好。
2 将自定义的日历View装入Fragment,以供Viewpager的适配器调用
public class CalendarItem extends Fragment implements NoteCalendar2.ChangeDateListener{ private static final String TAG = "CalendarItem"; private Activity mActivity; NoteDataBaseManager noteDBManager; int pos; NoteCalendar2 calendarView; int calendar_year; int calendar_month; int calendar_selected_year; int calendar_selected_month; int calendar_selected_day; boolean sync; CallBack mCallBack; public void setCalendarCallBack(CallBack cb){ mCallBack = cb; } public CalendarItem(){} public CalendarItem(int pos,int sY,int sM,int sD,boolean b) { this.pos = pos; calendar_year = 1900 + (pos / 12); calendar_month = pos % 12 +1; calendar_selected_year = sY; calendar_selected_month = sM; calendar_selected_day = sD; sync = b; } @Override public void onAttach(Activity mActivity) { super.onAttach(mActivity); this.mActivity = mActivity; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //initDBManager(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_calendar_item, container, false); calendarView = (NoteCalendar2) v.findViewById(R.id.calendar); calendarView.setSelectedDay(calendar_selected_year, calendar_selected_month, calendar_selected_day); calendarView.setYearAndMonth(calendar_year,calendar_month); calendarView.setOnChangeDateListener(this); calendarView.setTouchable(sync); return v; } @Override public void onChangeSelectedDate(int year, int month, int day) { // TODO Auto-generated method stub mCallBack.onChangeSelectedDate(year, month, day); } public interface CallBack{ abstract void onChangeSelectedDate(int year,int month ,int day); } }在onCreateView加载自定义的View,并让该Fragment 实现自定义View的回调,接受日期选中事件,并定义自身的回调接口,暴露给上层。
3 实现FragmentStatePagerAdapter
private class CalendarPagerAdapter extends FragmentStatePagerAdapter { private static final int YEAR_MAX = 2100; private static final int YEAR_MIN = 1900; private boolean sync; public CalendarPagerAdapter(FragmentManager fm) { super(fm); // TODO Auto-generated constructor stub } public CalendarPagerAdapter(android.support.v4.app.Fragment fragment, boolean b) { super(fragment.getChildFragmentManager()); sync = b; } @Override public Fragment getItem(int pos) { // TODO Auto-generated method stub CalendarItem ci = new CalendarItem(pos, calendar_selected_year, calendar_selected_month, calendar_selected_day, sync); ci.setCalendarCallBack(CalendarFragment2.this); return ci; } @Override public int getCount() { // TODO Auto-generated method stub return (YEAR_MAX - YEAR_MIN) * 12; } }
简单定义适配器,算出总共有多少个月,每个Fragment就是上面写的,并且实现它的回调接受日期选中事件。\
</pre><pre code_snippet_id="494662" snippet_file_name="blog_20141023_5_3057056" name="code" class="java">4 在Viewpager中添加适配器
</pre><pre code_snippet_id="494662" snippet_file_name="blog_20141023_6_8455249" name="code" class="java">MyViewPager mViewPager; ... mViewPager = (MyViewPager) v.findViewById(R.id.calendar_pager); mViewPagerAdapter = new CalendarPagerAdapter( CalendarFragment2.this, sync); mViewPager.setAdapter(mViewPagerAdapter); ...
上面的代码有bug,Fragment最好不要加带参数的构造方法,如
public CalendarItem(int pos,int sY,int sM,int sD,boolean b) { this.pos = pos; calendar_year = 1900 + (pos / 12); calendar_month = pos % 12 +1; calendar_selected_year = sY; calendar_selected_month = sM; calendar_selected_day = sD; sync = b; }
</pre><pre code_snippet_id="494662" snippet_file_name="blog_20141023_9_4823772" name="code" class="java">CalendarItem ci = new CalendarItem(pos, calendar_selected_year, calendar_selected_month, calendar_selected_day, sync); ci.setCalendarCallBack(CalendarFragment2.this);
</pre><pre code_snippet_id="494662" snippet_file_name="blog_20141023_11_7712928" name="code" class="java">改用 setArguments(args)这个方法向fragment传参就不会在最小化恢复后报错。
另外
ci.setCalendarCallBack(CalendarFragment2.this);这种方式实现回调可能在最小化后丢失回调对象跑出NullPointerException。
最好写成这样
@Override
public void onAttach(Activity mActivity) {
super.onAttach(mActivity);
this.mActivity = mActivity;
mCallBack = (CallBack)mActivity;
}
另外想要向fragment共享复杂类型对象,可以通过继承Application的方法,在Application对象中提供对象的接口。不要把对象加在Fragment的构造函数里,因为程序最小化后可能调用无参的默认的构造行数。
如果你觉得平移的滑动方式不够炫酷可以使用JazzyViewPager满足你的需求,封装了多种左右滑动的切换动画。
如果滑动觉得卡顿,可以像我一样自定义Viewpager,在onTouchEvent作判断,超过一段距离就返回true,把touch事件消耗掉,而不是传递给子view。
相关文章推荐
- ViewPager-------Fragment作为ViewPager的数据源(FragmentStatePagerAdapter)
- ViewPager Adapter FragmentStatePagerAdapter FragmentPagerAdapter 使用详解
- ViewPager+FragmentStatePagerAdapter 实现菜单
- android fragmentStateViewPagerAdapter 介绍
- 通过viewpager+fragment结合FragmentPagerAdapter实现自定义view定时轮转
- FragmentPagerAdapter与FragmentStatePagerAdapter的区别+ViewPager数据刷新问题详解
- ViewPager适配器学习记录( pageAdapter和FragmentPagerAdapter/FragmentStatePagerAdapter))
- [android]与 ViewPager fragment里面fragment和 FragmentStatePagerAdapter 的结果,在异常 (与完整的示例)
- Fragment与Viewpager及FragmentStatePagerAdapter
- 转载---ViewPager,PagerAdapter,FragmentPagerAdapter和FragmentStatePagerAdapter的分析对比
- ViewPager+Fragment+FragmentPagerAdapter,设置自定义刷新
- ViewPager搭配FragmentStatePagerAdapter如何获取Fragment的引用
- 【控件篇】ViewPager+FragmentStatePagerAdapter 页面切换案例详解
- Android-ViewPager(FragmentPagerAdapter 和 FragmentStatePagerAdapter)
- viewpager : FragmentStatePagerAdapter和FragmentPagerAdapter
- 【FastDev4Android框架开发】HorizontalScrollView,Fragment,FragmentStatePagerAdapter打造网易新闻Tab及滑动页面效果(三十六)
- TabLayout+Fragment+ViewPager+FragmentStatePagerAdapter实现Tab标签
- ViewPager适配器学习记录( pageAdapter和FragmentPagerAdapter/FragmentStatePagerAdapter))
- FragmentPager +ViewPager +FragmentStatePagerAdapter详解
- PagerAdapter、FragmentPagerAdapter及FragmentStatePagerAdapter与Viewpager