最近碰到同样的问题。我从你的框架布局的想法开始,上面有一堆视图,但对性能和我必须做的大量工作来绘制和自定义,比如项目下方的网格,我并不满意。
所以我继续集成的一个解决方案是扩展View
类,覆盖它的onDraw
和相关的方法,然后在那里绘制我需要的任何东西。
在这种情况下,我可以对正在发生的事情以及我希望它的外观进行大量控制。不用说,我可以并且确实实现了一些性能改进,例如将底层网格缓存到位图等等,当您使用像布局和视图组合这样高级别的东西时,这是很难实现的。
在任何情况下,您或遇到相同问题的任何人都可能希望从简单的事情开始,例如(代码不在我的脑海中):
public class MyDayTimeline extends View {
String [] timeMarkers; // time strings, like "9.00 AM" or something
Rect [] eventRects; // a bunch of rectangles, which correspond to your events
final int rowCount;
final int rowHeightPx;
final int firstColumnWidthPx;
// ..... constructors, size and painting initialization, event position calculation and whatnot
@Override
protected void onDraw(Canvas canvas) {
canvas.drawLine(firstColumnWidthPx, 0, firstColumnWidthPx, getMeasuredHeight(), delimeterLinesPaint); // draw a delimeter between time markers and the rest of the control space
for (int i = 1; i < rowCount; i++) {
canvas.drawLine(0, i * rowHeightPx, getMeasuredWidth(), i * rowHeightPx, delimeterLinesPaint); // draw a bunch of lines separating each hour
}
for(int i = 0; i < eventRects.size(); i++) { // draw a bunch rectangles, each representing an event
canvas.drawRect(eventRects[i], eventPaintBackgroundPaint);
canvas.drawRect(eventRects[i], eventPaintBorderPaint);
}
}
}
乍一看,需要完成的工作量似乎相当庞大,但实际上并非如此,如果您首先计划您需要做什么,然后再去做。我选择了这样的东西:
onDraw()
首先在覆盖中绘制一个简单的时间线网格,所有尺寸和颜色都经过硬编码。
- 覆盖
onMeasure()
和onSizeChanged()
,开始相应地更改您的大小控制字段。24 * rowHeightPx
无论测量规格如何,我都采用简单的尺寸来确定我在哪里占据所有可用空间的宽度,并大胆地要求高度。
- 使用“canvas.drawText()”在时间网格中放置一堆时间里程碑。
- 想出一个结构来定义你的事件。我选择了开始和结束日期/时间、一些主题字符串和一组矩形。当控件的大小发生变化时,我会重新计算每个事件应该采用的矩形。
- 实施事件绘图,
onDraw()
使您先前定义的结构和位置计算到位。
- 处理特定情况,例如跨越几天的事件。
onTouchEvent()
开始用什么东西处理水龙头。添加一些日志以查看您是否正确执行了命中测试,如果需要,开始使用突出显示的颜色重绘事件框架等等。
- 从可重用性的角度来看,让您的控制更好。为某些属性定义 getter 和 setter,在 中定义自定义属性
attrs.xml
,在初始化代码中实现对这些属性的处理。公开一些自定义侦听器,例如 EventClickedListener 或其他东西。
- 在此之上添加一些支持控件。将整个内容包裹在 a 中
ScrollView
,我使用 aViewPager
来处理水平滑动并显示前一天/第二天/一周/一个月。
- 给定几乎准备好的一天时间线,从中提取基类并开始处理其他时间线,例如周和月的时间线。
然后继续改进你的控制,直到你和你的队友对结果感到满意。显然,您需要在每个步骤中不断地测试、调试和修复您的控件,因此拥有一堆测试用例非常有帮助。
当我处理周和月概览时,我在使用标准 Calendar API 时也遇到了一些问题,因此您可能会考虑使用其他库,例如 Joda Time,但那是另一回事了。