一直想给最近在做的笔记本加一个日历查找的功能,但是google源生的calendarView似乎只能上下滑动,而且不支持在日历上标注文字。
本人才浅,面对谷歌日历源码无从下手,于是想自己开发一个可以左右滑动,并且支持标注当日记录数的日历。
实现效果如图
实现思路:
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。