From d37559daa7c7341469b8147c2deb952820e3fe00 Mon Sep 17 00:00:00 2001 From: liyujiang Date: Wed, 5 Jan 2022 16:28:01 +0800 Subject: [PATCH] fix: #288 --- .../calendarpicker/CalendarPicker.java | 35 ++++++++++++++++- .../calendarpicker/core/CalendarAdapter.java | 39 ++++++++++++++----- .../calendarpicker/core/CalendarView.java | 14 ++++++- .../calendarpicker/core/ItemViewProvider.java | 29 ++++++++++++++ .../activity/CalendarPickerActivity.java | 30 +++++++++++++- .../res/layout/activity_picker_calendar.xml | 26 ++++++++++++- 6 files changed, 158 insertions(+), 15 deletions(-) create mode 100644 CalendarPicker/src/main/java/com/github/gzuliyujiang/calendarpicker/core/ItemViewProvider.java diff --git a/CalendarPicker/src/main/java/com/github/gzuliyujiang/calendarpicker/CalendarPicker.java b/CalendarPicker/src/main/java/com/github/gzuliyujiang/calendarpicker/CalendarPicker.java index 138defc8..a2bee280 100644 --- a/CalendarPicker/src/main/java/com/github/gzuliyujiang/calendarpicker/CalendarPicker.java +++ b/CalendarPicker/src/main/java/com/github/gzuliyujiang/calendarpicker/CalendarPicker.java @@ -13,18 +13,21 @@ package com.github.gzuliyujiang.calendarpicker; +import android.annotation.SuppressLint; import android.app.Activity; import android.text.TextUtils; import android.view.View; import androidx.annotation.NonNull; import androidx.annotation.StyleRes; +import androidx.recyclerview.widget.RecyclerView; import com.github.gzuliyujiang.calendarpicker.core.CalendarAdapter; import com.github.gzuliyujiang.calendarpicker.core.CalendarView; import com.github.gzuliyujiang.calendarpicker.core.ColorScheme; import com.github.gzuliyujiang.calendarpicker.core.DateUtils; import com.github.gzuliyujiang.calendarpicker.core.FestivalProvider; +import com.github.gzuliyujiang.calendarpicker.core.ItemViewProvider; import com.github.gzuliyujiang.calendarpicker.core.OnDateSelectedListener; import com.github.gzuliyujiang.dialog.DialogConfig; import com.github.gzuliyujiang.dialog.DialogStyle; @@ -47,6 +50,7 @@ public class CalendarPicker extends ModalDialog implements OnDateSelectedListene private ColorScheme colorScheme; private boolean singleMode = false; private FestivalProvider festivalProvider; + private ItemViewProvider itemViewProvider; private Date minDate, maxDate; private Date selectDate, startDate, endDate; private String noteFrom, noteTo; @@ -139,6 +143,24 @@ public void onRangeSelected(@NonNull Date start, @NonNull Date end) { endDate = end; } + /** + * 启用横向滑动模式 + */ + public void enablePagerSnap() { + setHeight(WRAP_CONTENT); + calendarView.enablePagerSnap(); + calendarView.getBodyView().addOnScrollListener(new RecyclerView.OnScrollListener() { + @SuppressLint("NotifyDataSetChanged") + @Override + public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { + if (newState != RecyclerView.SCROLL_STATE_IDLE) { + return; + } + calendarView.getAdapter().notifyDataSetChanged(); + } + }); + } + /** * 设置配色方案 */ @@ -251,7 +273,7 @@ public void setIntervalNotes(String noteFrom, String noteTo) { } /** - * 设置是否展示节日文本 + * 设置节日文本提供者 */ public void setFestivalProvider(FestivalProvider festivalProvider) { this.festivalProvider = festivalProvider; @@ -260,11 +282,22 @@ public void setFestivalProvider(FestivalProvider festivalProvider) { } } + /** + * 设置条目视图提供者 + */ + public void setItemViewProvider(ItemViewProvider itemViewProvider) { + this.itemViewProvider = itemViewProvider; + if (initialized) { + refreshData(); + } + } + private void refreshData() { calendarView.setColorScheme(colorScheme); calendarAdapter.notify(false); calendarAdapter.single(singleMode); calendarAdapter.festivalProvider(festivalProvider); + calendarAdapter.itemViewProvider(itemViewProvider); if (singleMode) { startDate = selectDate; endDate = selectDate; diff --git a/CalendarPicker/src/main/java/com/github/gzuliyujiang/calendarpicker/core/CalendarAdapter.java b/CalendarPicker/src/main/java/com/github/gzuliyujiang/calendarpicker/core/CalendarAdapter.java index feaae566..5554f539 100644 --- a/CalendarPicker/src/main/java/com/github/gzuliyujiang/calendarpicker/core/CalendarAdapter.java +++ b/CalendarPicker/src/main/java/com/github/gzuliyujiang/calendarpicker/core/CalendarAdapter.java @@ -14,6 +14,7 @@ package com.github.gzuliyujiang.calendarpicker.core; import android.annotation.SuppressLint; +import android.content.Context; import android.graphics.Typeface; import android.view.Gravity; import android.view.View; @@ -44,6 +45,7 @@ public class CalendarAdapter extends RecyclerView.Adapter im private final Interval selectNote = new Interval<>(); private boolean singleMode = false; private FestivalProvider festivalProvider; + private ItemViewProvider itemViewProvider; private Date lastClickDate = null; private OnDateSelectedListener onDateSelectedListener; @@ -82,6 +84,14 @@ public CalendarAdapter festivalProvider(FestivalProvider value) { return this; } + public CalendarAdapter itemViewProvider(ItemViewProvider value) { + itemViewProvider = value; + if (notify) { + refresh(); + } + return this; + } + public CalendarAdapter valid(Date from, Date to) { valid.left(from); valid.right(to); @@ -190,24 +200,32 @@ public void setOnCalendarSelectedListener(OnDateSelectedListener onDateSelectedL @NonNull @Override public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - LinearLayout linearLayout = new LinearLayout(parent.getContext()); + Context context = parent.getContext(); + LinearLayout linearLayout = new LinearLayout(context); linearLayout.setOrientation(LinearLayout.VERTICAL); linearLayout.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); - TextView titleView = new TextView(parent.getContext()); - titleView.setGravity(Gravity.CENTER); - titleView.setTextSize(14); - titleView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); - int padding = (int) (parent.getResources().getDisplayMetrics().density * 10); - titleView.setPadding(padding, padding, padding, padding); + TextView titleView = itemViewProvider == null ? null : itemViewProvider.provideTitleView(context); + if (titleView == null) { + titleView = new TextView(context); + titleView.setGravity(Gravity.CENTER); + titleView.setTextSize(14); + titleView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); + int padding = (int) (parent.getResources().getDisplayMetrics().density * 10); + titleView.setPadding(padding, padding, padding, padding); + } linearLayout.addView(titleView, new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); - MonthView monthView = new MonthView(parent.getContext()); - linearLayout.addView(monthView, new ViewGroup.LayoutParams( + MonthView monthView = itemViewProvider == null ? null : itemViewProvider.provideMonthView(context); + if (monthView == null) { + monthView = new MonthView(context); + } + monthView.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + linearLayout.addView(monthView); return new VH(linearLayout, titleView, monthView); } @@ -234,6 +252,9 @@ public final int getDatePosition(Date date) { if (size <= 1) { return 0; } + if (date == null) { + return 0; + } long time = date.getTime(); if (time <= dates.get(0).getTime()) { return 0; diff --git a/CalendarPicker/src/main/java/com/github/gzuliyujiang/calendarpicker/core/CalendarView.java b/CalendarPicker/src/main/java/com/github/gzuliyujiang/calendarpicker/core/CalendarView.java index 04c2086f..72e0c624 100644 --- a/CalendarPicker/src/main/java/com/github/gzuliyujiang/calendarpicker/core/CalendarView.java +++ b/CalendarPicker/src/main/java/com/github/gzuliyujiang/calendarpicker/core/CalendarView.java @@ -22,6 +22,7 @@ import androidx.annotation.Nullable; import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.PagerSnapHelper; import androidx.recyclerview.widget.RecyclerView; import com.github.gzuliyujiang.calendarpicker.R; @@ -54,10 +55,15 @@ public CalendarView(Context context, @Nullable AttributeSet attrs, int defStyleA weekView.setAdapter(weekAdapter); weekView.setSelector(new ColorDrawable(Color.TRANSPARENT)); bodyView = findViewById(R.id.calendar_body_content); - bodyView.setLayoutManager(new LinearLayoutManager(context)); + bodyView.setLayoutManager(new LinearLayoutManager(context, RecyclerView.VERTICAL, false)); bodyView.setAdapter(calendarAdapter); } + public void enablePagerSnap() { + bodyView.setLayoutManager(new LinearLayoutManager(getContext(), RecyclerView.HORIZONTAL, false)); + new PagerSnapHelper().attachToRecyclerView(bodyView); + } + public void setColorScheme(ColorScheme colorScheme) { weekAdapter.setColorScheme(colorScheme); calendarAdapter.colorScheme(colorScheme); @@ -72,7 +78,11 @@ public final RecyclerView getBodyView() { } public final LinearLayoutManager getLayoutManager() { - return (LinearLayoutManager) bodyView.getLayoutManager(); + RecyclerView.LayoutManager layoutManager = bodyView.getLayoutManager(); + if (layoutManager instanceof LinearLayoutManager) { + return (LinearLayoutManager) layoutManager; + } + throw new IllegalArgumentException("Layout manager must instance of LinearLayoutManager"); } public final CalendarAdapter getAdapter() { diff --git a/CalendarPicker/src/main/java/com/github/gzuliyujiang/calendarpicker/core/ItemViewProvider.java b/CalendarPicker/src/main/java/com/github/gzuliyujiang/calendarpicker/core/ItemViewProvider.java new file mode 100644 index 00000000..b97875c3 --- /dev/null +++ b/CalendarPicker/src/main/java/com/github/gzuliyujiang/calendarpicker/core/ItemViewProvider.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016-present 贵州纳雍穿青人李裕江<1032694760@qq.com> + * + * The software is licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package com.github.gzuliyujiang.calendarpicker.core; + +import android.content.Context; +import android.widget.TextView; + +/** + * @author liyuj + * @since 2022/1/5 16:03 + */ +public interface ItemViewProvider { + + TextView provideTitleView(Context context); + + MonthView provideMonthView(Context context); + +} diff --git a/app/src/main/java/com/github/gzuliyujiang/fallback/activity/CalendarPickerActivity.java b/app/src/main/java/com/github/gzuliyujiang/fallback/activity/CalendarPickerActivity.java index c5b6940d..858b3c74 100644 --- a/app/src/main/java/com/github/gzuliyujiang/fallback/activity/CalendarPickerActivity.java +++ b/app/src/main/java/com/github/gzuliyujiang/fallback/activity/CalendarPickerActivity.java @@ -48,12 +48,23 @@ public class CalendarPickerActivity extends BackAbleActivity { protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_picker_calendar); - CalendarView calendarView = findViewById(R.id.calendar_picker_body); Date minDate = new Date(System.currentTimeMillis() - 5 * android.text.format.DateUtils.DAY_IN_MILLIS); Calendar calendar = DateUtils.calendar(minDate); calendar.add(Calendar.MONTH, 3); Date maxDate = calendar.getTime(); - calendarView.getAdapter() + CalendarView horizontalCalendarView = findViewById(R.id.calendar_picker_body_horizontal); + horizontalCalendarView.enablePagerSnap(); + horizontalCalendarView.getAdapter() + .notify(false) + .single(false) + .festivalProvider(new MyFestivalProvider()) + .valid(minDate, maxDate) + .intervalNotes("开始", "结束") + .select(minDate.getTime(), minDate.getTime() + 5 * android.text.format.DateUtils.DAY_IN_MILLIS) + .range(minDate, maxDate) + .refresh(); + CalendarView verticalCalendarView = findViewById(R.id.calendar_picker_body_vertical); + verticalCalendarView.getAdapter() .notify(false) .single(false) .festivalProvider(new MyFestivalProvider()) @@ -135,6 +146,21 @@ public void onSingleDatePicked(@NonNull Date date) { picker.show(); } + public void onHorizontalCalendarPicker(View view) { + CalendarPicker picker = new CalendarPicker(this); + picker.enablePagerSnap(); + picker.setRangeDateOnFuture(3); + picker.setFestivalProvider(new MyFestivalProvider()); + picker.setOnSingleDatePickListener(new OnSingleDatePickListener() { + @Override + public void onSingleDatePicked(@NonNull Date date) { + singleTimeInMillis = date.getTime(); + Toast.makeText(getApplicationContext(), DateFormat.getDateTimeInstance().format(date), Toast.LENGTH_SHORT).show(); + } + }); + picker.show(); + } + private static class MyFestivalProvider implements FestivalProvider { @Override public String provideText(Date date) { diff --git a/app/src/main/res/layout/activity_picker_calendar.xml b/app/src/main/res/layout/activity_picker_calendar.xml index c28c62ec..1cefa136 100644 --- a/app/src/main/res/layout/activity_picker_calendar.xml +++ b/app/src/main/res/layout/activity_picker_calendar.xml @@ -41,8 +41,32 @@ android:onClick="onCalendarDateSingle" android:text="日历单个日期选择(如航班出发日期)" /> +