
CalendarViewAdapter.saveDate(selectedDate);
onSelectDateListener.onSelectDate(selectedDate);
seedDate = selectedDate;
} else if (weeks[row].days[col].getState() == State.PAST_MONTH){
selectedDate = weeks[row].days[col].getDate();
CalendarViewAdapter.saveDate(selectedDate);
onSelectDateListener.onSelectOtherMonth(-1);
onSelectDateListener.onSelectDate(selectedDate);
} else if (weeks[row].days[col].getState() == State.NEXT_MONTH){
selectedDate = weeks[row].days[col].getDate();
CalendarViewAdapter.saveDate(selectedDate);
onSelectDateListener.onSelectOtherMonth(1);
onSelectDateListener.onSelectDate(selectedDate);
}
} else {
weeks[row].days[col].setState(State.SELECT);
selectedDate = weeks[row].days[col].getDate();
CalendarViewAdapter.saveDate(selectedDate);
onSelectDateListener.onSelectDate(selectedDate);
seedDate = selectedDate;
}
}
}
- 调用Renderer的draw方法时使用dayRenderer.drawDay(canvas , weeks[row].days[col]),dayRenderer是一个接口,在lib中有一个DayView 的抽象类实现该接口。 其中的drawDay方法完成了对该天到calendar的canvas上的绘制
@Override
public void drawDay(Canvas canvas , Day day) {
this.day = day;
refreshContent();
int saveId = canvas.save();
canvas.translate(day.getPosCol() * getMeasuredWidth(),
day.getPosRow() * getMeasuredHeight());
draw(canvas);
canvas.restoreToCount(saveId);
}
- 使用继承自ViewPager的MonthPager来存放calendar的view
viewPageChangeListener = new ViewPager.onPageChangeListener() {}
//新建viewPagerChangeListener
@Override
protected void onSizeChanged(int w, int h, int oldW, int oldH) {
cellHeight = h / 6;
super.onSizeChanged(w, h, oldW, oldH);
}//重写onSizeChanged,获取dayView的高度
public int getTopMovableDistance() {
CalendarViewAdapter calendarViewAdapter = (CalendarViewAdapter) getAdapter();
rowIndex = calendarViewAdapter.getPagers().get(currentPosition % 3).getSelectedRowIndex();
return cellHeight * rowIndex;
}//计算周月切换时在到达选中行之前MonthPager收起的距离
public int getRowIndex() {
CalendarViewAdapter calendarViewAdapter = (CalendarViewAdapter) getAdapter();
rowIndex = calendarViewAdapter.getPagers().get(currentPosition % 3).getSelectedRowIndex();
Log.e(“ldf”,"getRowIndex = " + rowIndex);
return rowIndex;
}//计算选中日期所在的行数
- 使用CalendarViewAdapter为MonthPager填充calendar的实例
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
this.currentPosition = position;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
if(position < 2){
return null;
}
Calendar calendar = calendars.get(position % calendars.size());
if(calendarType == CalendarAttr.CalendayType.MONTH) {
CalendarDate current = seedDate.modifyMonth(position - MonthPager.CURRENT_DAY_INDEX);
current.setDay(1);//每月的种子日期都是1号
calendar.showDate(current);
} else {
CalendarDate current = seedDate.modifyWeek(position - MonthPager.CURRENT_DAY_INDEX);
if(weekArrayType == 1) {
calendar.showDate(Utils.getSaturday(current));
} else {
calendar.showDate(Utils.getSunday(current));
}//每周的种子日期为这一周的最后一天
calendar.updateWeek(rowCount);
}
if (container.getChildCount() == calendars.size()) {
container.removeView(calendars.get(position % 3));
}
if(container.getChildCount() < calendars.size()) {
container.addView(calendar, 0);
} else {
container.addView(calendar, position % 3);
}
return calendar;
}
-
日历在切换周月时切换日历中填充的数据
-
在月模式切换成周模式时,将当前页的seedDate拿出来刷新本页数据,并且更新指定行数的周数据,然后得到seedDate下一周的周日作为下一页的seedDate,刷新下一页的数据,并且更新指定行数的周数据。上一页同理
-
也是说假设我当前选择的是6月12号周日,处于日历的第二行,也是说下一页的seedDate是6月19号,然后刷新6月19号所在周的数据到选定的第二行。
-
当切换周月时,把三页的数据都会重新刷新一遍,以保证数据的正确性。
public void switchToMonth() {
if(calendars != null && calendars.size() > 0 && calendarType != CalendarAttr.CalendayType.MONTH){
calendarType = CalendarAttr.CalendayType.MONTH;
MonthPager.CURRENT_DAY_INDEX = currentPosition;
Calendar v = calendars.get(currentPosition % 3);//0
seedDate = v.getSeedDate();
Calendar v1 = calendars.get(currentPosition % 3);//0
v1.switchCalendarType(CalendarAttr.CalendayType.MONTH);
v1.showDate(seedDate);
Calendar v2 = calendars.get((currentPosition - 1) % 3);//2
v2.switchCalendarType(CalendarAttr.CalendayType.MONTH);
CalendarDate last = seedDate.modifyMonth(-1);
last.setDay(1);
v2.showDate(last);
Calendar v3 = calendars.get((currentPosition + 1) % 3);//1
v3.switchCalendarType(CalendarAttr.CalendayType.MONTH);
CalendarDate next = seedDate.modifyMonth(1);
next.setDay(1);
v3.showDate(next);
}
}
public void switchToWeek(int rowIndex) {
rowCount = rowIndex;
if(calendars != null && calendars.size() > 0 && calendarType != CalendarAttr.CalendayType.WEEK){
calendarType = CalendarAttr.CalendayType.WEEK;
MonthPager.CURRENT_DAY_INDEX = currentPosition;
Calendar v = calendars.get(currentPosition % 3);
seedDate = v.getSeedDate();
rowCount = v.getSelectedRowIndex();
Calendar v1 = calendars.get(currentPosition % 3);
v1.switchCalendarType(CalendarAttr.CalendayType.WEEK);
v1.showDate(seedDate);
v1.updateWeek(rowIndex);
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
Calendar v2 = calendars.get((currentPosition - 1) % 3);
v2.switchCalendarType(CalendarAttr.CalendayType.WEEK);
CalendarDate last = seedDate.modifyWeek(-1);
if(weekArrayType == 1) {
v2.showDate(Utils.getSaturday(last));
} else {
v2.showDate(Utils.getSunday(last));
}//每周的种子日期为这一周的最后一天
v2.updateWeek(rowIndex);
Calendar v3 = calendars.get((currentPosition + 1) % 3);
v3.switchCalendarType(CalendarAttr.CalendayType.WEEK);
CalendarDate next = seedDate.modifyWeek(1);
if(weekArrayType == 1) {
v3.showDate(Utils.getSaturday(next));
} else {
v3.showDate(Utils.getSunday(next));
}//每周的种子日期为这一周的最后一天
v3.updateWeek(rowIndex);
}
}
-
使用CoordinateLayout的特性来做周月模式切换
-
1.RecyclerViewBehavior
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, RecyclerView child,
View directTargetChild, View target, int nestedScrollAxes) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) child.getLayoutManager();
if(linearLayoutManager.findFirstCompletelyVisibleItemPosition() > 0) {
return false;
}
boolean isVertical = (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;
int firstRowVerticalPosition =
(child == null || child.getChildCount() == 0) ? 0 : child.getChildAt(0).getTop();
boolean recycleviewTopStatus = firstRowVerticalPosition >= 0;
return isVertical && (recycleviewTopStatus || !Utils.isScrollToBottom()) && child == directTargetChild;
}
@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, RecyclerView child,
View target, int dx, int dy, int[] consumed) {
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);
if (child.getTop() <= initOffset && child.getTop() >= minOffset) {
consumed[1] = Utils.scroll(child, dy, minOffset, initOffset);
saveTop(child.getTop());
}
}
@Override
public void onStopNestedScroll(final CoordinatorLayout parent, final RecyclerView child, View target) {
Log.e(“ldf”,“onStopNestedScroll”);
super.onStopNestedScroll(parent, child, target);
if (!Utils.isScrollToBottom()) {
if (initOffset - Utils.loadTop() > Utils.getTouchSlop(context)){
scrollTo(parent, child, minOffset, 200);
} else {
scrollTo(parent, child, initOffset, 80);
}
} else {
if (Utils.loadTop() - minOffset > Utils.getTouchSlop(context)){
scrollTo(parent, child, initOffset, 200);
} else {
scrollTo(parent, child, minOffset, 80);
}
}
}
- (2)MonthPagerBehavior 当recyclerView滑动式,MonthPager做相应的变化。
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, MonthPager child, View dependency) {
Log.e(“ldf”,“onDependentViewChanged”);
CalendarViewAdapter calendarViewAdapter = (CalendarViewAdapter) child.getAdapter();
if (dependentViewTop != -1) {
int dy = dependency.getTop() - dependentViewTop; //dependency对其依赖的view(本例依赖的view是RecycleView)
int top = child.getTop();
if( dy > touchSlop){
calendarViewAdapter.switchToMonth();
} else if(dy < - touchSlop){
calendarViewAdapter.switchToWeek(child.getRowIndex());
}
if (dy > -top){
dy = -top;
}
if (dy < -top - child.getTopMovableDistance()){
dy = -top - child.getTopMovableDistance();
}
child.offsetTopAndBottom(dy);
} else {
initRecyclerViewTop = dependency.getTop();
}
dependentViewTop = dependency.getTop();
top = child.getTop();
if((initRecyclerViewTop - dependentViewTop) >= child.getCellHeight()) {
Utils.setScrollToBottom(false);
calendarViewAdapter.switchToWeek(child.getRowIndex());
initRecyclerViewTop = dependentViewTop;
}
if((dependentViewTop - initRecyclerViewTop) >= child.getCellHeight()) {
Utils.setScrollToBottom(true);
calendarViewAdapter.switchToMonth();
initRecyclerViewTop = dependentViewTop;
}
return true;
// TODO: 16/12/8 dy为负时表示向上滑动,dy为正时表示向下滑动,dy为零时表示滑动停止
}
- 使用IDayRender来实现自定义的日历效果
DayView实现IDayRenderer,我们新建一个CustomDayView继承自DayView,在里面作自定义的显示
public CustomDayView(Context context, int layoutResource) {
super(context, layoutResource);
dateTv = (TextView) findViewById(R.id.date);
marker = (ImageView) findViewById(R.id.maker);
selectedBackground = findViewById(R.id.selected_background);
todayBackground = findViewById(R.id.today_background);
}
@Override
public void refreshContent() {
renderToday(day.getDate());
renderSelect(day.getState());
renderMarker(day.getDate(), day.getState());
super.refreshContent();
}
使用方法
XML布局
- 新建XML布局
RecyclerView的layout_behavior为com.ldf.calendar.behavior.RecyclerViewBehavior
android:id="@+id/content"
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:layout_weight=“1”>
android:id="@+id/calendar_view" android:layout_width=“match_parent” android:layout_height=“300dp” android:background="#fff">
android:id="@+id/list"
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
app:layout_behavior=“com.ldf.calendar.behavior.RecyclerViewBehavior”
android:background="#c2c2c2"
android:layout_gravity=“bottom”/>
自定义日历样式- 新建CustomDayView继承自DayView并重写refreshContent 和 copy 两个方法
@Override
public void refreshContent() {
//你的代码 你可以在这里定义你的显示规则
super.refreshContent();
}
@Override
public IDayRenderer copy() {
return new CustomDayView(context , layoutResource);
}
- 新建CustomDayView实例,并作为参数构建CalendarViewAdapter
CustomDayView customDayView = new CustomDayView(
context , R.layout.custom_day);
calendarAdapter = new CalendarViewAdapter(
context ,
onSelectDateListener ,
Calendar.MONTH_TYPE ,
customDayView);
初始化View- 目前来看 相比于Dialog选择日历 我的控件更适合于Activity/Fragment在Activity的onCreate 或者Fragment的onCreateView 你需要实现这两个方法来启动日历并装填进数据
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_syllabus);
initCalendarView();
}
private void initCalendarView() {
initListener();
CustomDayView customDayView = new CustomDayView(
context , R.layout.custom_day);
calendarAdapter = new CalendarViewAdapter(
context ,
onSelectDateListener ,
Calendar.MONTH_TYPE ,
customDayView);
initMarkData();
initMonthPager();
}
使用此方法回调日历点击事件
private void initListener() {
onSelectDateListener = new onSelectDateListener() {
@Override
public void onSelectDate(CalendarDate date) {
//your code
}
@Override
public void onSelectOtherMonth(int offset) {
//偏移量 -1表示上一个月 , 1表示下一个月
monthPager.selectOtherMonth(offset);
}
};
}
使用此方法初始化日历标记数据
private void initMarkData() {
HashMap markData = new HashMap<>();
//1表示红点,0表示灰点
markData.put(“2017-8-9” , “1”);
markData.put(“2017-7-9” , “0”);
markData.put(“2017-6-9” , “1”);
markData.put(“2017-6-10” , “0”);
calendarAdapter.setMarkData(markData);
}
使用此方法给MonthPager添加上相关监听
monthPager.addonPageChangeListener(new MonthPager.onPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
mCurrentPage = position;
currentCalendars = calendarAdapter.getAllItems();
if(currentCalendars.get(position % currentCalendars.size()) instanceof Calendar){
//you code
}
}
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)