我在Android应用程序中使用android多产材料calendarview外部库实现了calendarview。现在我必须在某些日期下面添加多个点指示符来指示每个日期的事件数。我试过但是在日期之下只有一个点。请帮忙
这是我的日历片段和装饰器类:
public class CalendarFragment extends Fragment {
private View v;
private List<Schedule> schedules = new ArrayList<Schedule>( );
private MaterialCalendarView calendarView;
public CalendarFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
try {
v = inflater.inflate(R.layout.fragment_calendar, container, false);
initViews();
schedules = ScheduleDAO.getInstance().getScheduleListWithId();
highlightDates(schedules);
} catch (ParseException e) {
e.printStackTrace();
}
return v;
}
private void highlightDates(List<Schedule>scheduleList) throws ParseException {
for (int position = 0;position<scheduleList.size();position++)
{
Schedule schedule = scheduleList.get(position);
if (schedule.getSessionStatus().equals("Incomplete")){
int color = R.color.colorPrimaryDark;
CurrentDayDecorator decorator = new CurrentDayDecorator(new Date(schedule.getScheduledDate()),color);
calendarView.addDecorator(decorator);
}else {
int color = R.color.lightgray;
CurrentDayDecorator decorator = new CurrentDayDecorator(new Date(schedule.getScheduledDate()),color);
calendarView.addDecorator(decorator);
}
}
}
private void initViews() {
calendarView = v.findViewById(R.id.calendarView);
}
}
Decorator class
public class CurrentDayDecorator implements DayViewDecorator {
private final int color;
private final CalendarDay day;
public CurrentDayDecorator(Date date,int color) {
this.color = color;
this.day = CalendarDay.from(date);
}
@Override
public boolean shouldDecorate(CalendarDay day) {
if (this.day.equals(day)){
return true;
}
return false;
}
@Override
public void decorate(DayViewFacade view) {
view.addSpan(new DotSpan(3,color));
}
}
答案 0 :(得分:1)
我遇到了类似的问题,发现this post非常有帮助。
通过MaterialViewCalendar API不支持您要执行的操作,因此您需要添加一些额外的帮助程序类。请注意,一个装饰器映射到一个点。因此,如果您希望在给定日期下有两个点,则该日期必须绑定到两个装饰器等。
解决问题的一种方法是执行以下操作:
将decorate
课程中的CurrentDayDecorator
- 方法更改为以下内容:
@Override
public void decorate(DayViewFacade view) {
LineBackgroundSpan span = new CustomSpan(color, xOffsets[spanType]);
view.addSpan(span);
}
如您所见,我们需要向您的CustomSpan
课程添加新课程(xOffsets
)和两个字段(spanType
和CurrentDayDecorator
)。 LineBackgroundSpan是包中包含的接口。
private static class CustomSpan extends DotSpan{
private int color;
private int xOffset;
private float radius = 3;
CustomSpan(int color, int xOffset){
this.color = color;
this.xOffset = xOffset;
}
/*Note! The following code is more or less copy-pasted from the DotSpan class. I have commented the changes below.*/
@Override
public void drawBackground(Canvas canvas, Paint paint, int left, int right, int top, int baseline,
int bottom, CharSequence text, int start, int end, int lnum) {
int oldColor = paint.getColor();
if (color != 0) {
paint.setColor(color);
}
int x = ((left + right) / 2); /*This is the x-coordinate right
below the date. If we add to x, we will draw the
circle to the right of the date and vice versa if we subtract from x.*/
canvas.drawCircle(x + xOffset, bottom + radius, radius, paint);
paint.setColor(oldColor);
}
}
所以剩下的就是给我们的CustomSpan提供一个偏移量。在我自己的装饰器方法中,我有一个可供选择的偏移数组。我选择哪一个取决于我创建的点。在我的应用程序中,我可以在日期下方放置最多4个点。在绘制它之前,我需要告诉我CurrentDayDecorator
它代表的4个点中的哪个点。
这就是我班级的样子(对你来说,只需将“EventDecorator”改为“CurrentDayDecorator”)
private static class EventDecorator implements DayViewDecorator {
private static final float DEFAULT_DOT_RADIUS = 4;
//Note that negative values indicate a relative offset to the LEFT
private static final int[] xOffsets = new int[]{0,-10,10,-20};
private int color;
private HashSet<CalendarDay> dates;
private float dotRadius;
private int spanType;
private EventDecorator(int color, float dotRadius, int spanType) {
this.color = color;
this.dotRadius = dotRadius;
this.dates = new HashSet<>();
this.spanType = spanType;
}
/*Note! I added this method so that I can add dates after object creation!*/
public boolean addDate(CalendarDay day){
return dates.add(day);
}
@Override
public boolean shouldDecorate(CalendarDay day) {
return dates.contains(day);
}
@Override
public void decorate(DayViewFacade view) {
LineBackgroundSpan span = new CustomSpan(color, xOffsets[spanType],DEFAULT_DOT_RADIUS);
view.addSpan(span);
}
}
现在,棘手的部分知道何时使用正确的相应spanType
创建DayViewDecorator。如果一天应该有两个点,则需要两个DayViewDecorators
(spanType
的值不同)。我所做的是我用“事件”跟踪所有日子,并用计数器将每个“多事之日”联系起来。换句话说,HashMap
将CalendarDay
映射到Integer
。然后,您浏览地图中的每个条目,并将给定日期添加到X个装饰器数量,其中X是事件的总数。在代码中,它看起来像这样:
EventDecorator[] decoratorArray = new EventDecorator[4]; //Max 4 dots
for(int i = 0; i<decoratorArray.length; i++)
decoratorArray[i] = new EventDecorator(myColor,myRadius,i);
/*dayInstanceMap contains all the mappings.*/
for(Map.Entry<CalendarDay,Integer> entry : dayInstanceMap.entrySet()){
CalendarDay currDay = entry.getKey();
Integer currDayCount = entry.getValue(); //If you have max amount of dots, check here if currDay is too large.
for(int i = 0; i<currDayCount; i++)
decoratorArray[i].addDate(currDay);
}
之后,只需将装饰器添加到MaterialCalendarView即可。
答案 1 :(得分:0)
LineBackgroundSpan
,从左到右绘制点class MultiDotSpan(
private val radius: Float = 3f,
private val colors: List<Int>
) : LineBackgroundSpan {
override fun drawBackground(
canvas: Canvas, paint: Paint,
left: Int, right: Int, top: Int, baseline: Int, bottom: Int,
charSequence: CharSequence,
start: Int, end: Int, lineNum: Int
) {
var position = (left + right) / 2 - (colors.size - 1) * radius
if (colors.size > 1) {
position - 2
}
colors.forEach { color ->
val oldColor = paint.color
if (color != 0) {
paint.color = color
}
canvas.drawCircle(position, bottom + radius, radius, paint)
paint.color = oldColor
position += radius * 2 + 2
}
}
}
class EventDecorator(
private val colors: List<Int>,
private var dates: List<CalendarDay> = emptyList()
) : DayViewDecorator {
override fun shouldDecorate(day: CalendarDay) = dates.contains(day)
override fun decorate(view: DayViewFacade) = with(view) {
addSpan(MultiDotSpan(8f, colors))
}
}
val eventDecorator = MCVEventDecorator(colors, events)
calendarView.addDecorator(eventDecorator)
注意:您将需要对不同数量的点(例如,单,双,三等)使用不同的装饰器