实施Android时间线日历的最佳方式

时间:2013-03-01 14:49:50

标签: android listview scrollview timeline

我想在iPhone中创建时间轴

enter image description here

事件时间可以是9.42,它应该从9.30的虚线下方开始绘制,其中%与9.30相差多远。

我能想到的唯一方法是将ScrollViewFrameLayout一起使用并以编程方式添加时间轴。

<ScrollView
        android:id="@+id/scrollView1"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" >

        <FrameLayout
            android:id="@+id/timeline"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >

        </FrameLayout>
    </ScrollView> 

如果我能够使用ListView代替ScrollView可能会更好,但我不知道如何在整个单元格中自由放置事件,因为如果事件从10.50开始。

描述此事件的文本必须穿过单元格。

有人可以建议我吗? 感谢。

1 个答案:

答案 0 :(得分:2)

最近陷入了同样的问题。我已经从你对framelayout的想法开始,在它上面有一堆视图,但我对绘制和自定义(例如,项目下面的网格)我必须做的工作并不是很满意。

因此我继续进行集成的解决方案是扩展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);
        }
    }
}

乍一看,需要完成的工作量似乎非常庞大,但实际上并非如此,如果您首先计划您需要做什么然后再做。我选择了这样的事情:

  1. 首先在onDraw()覆盖中绘制一个简单的时间轴网格,所有尺寸和颜色都是硬编码的。
  2. 覆盖onMeasure()onSizeChanged(),开始相应地更改尺寸控制字段。我选择了简单的尺寸来确定我在宽度方面采用所有可用空间的方式,并且无论测量规格如何,都要求24 * rowHeightPx高度方向。
  3. 使用'canvas.drawText()'在时间网格中放置了一堆时间里程碑。
  4. 想出一个定义事件的结构。我选择了开始和结束日期/时间,一些主题字符串和一系列矩形。当控件大小发生变化时,我会重新计算每个事件应该采用的矩形。
  5. onDraw()中实施事件绘图,其中包含您之前定义的结构和位置计算。
  6. 处理特定情况,例如跨越几天的事件。
  7. 开始处理点击onTouchEvent()或其他内容。添加一些日志记录以查看您是否正确执行了命中测试,如果需要,可以使用突出显示的颜色重新绘制事件框架等等。
  8. 从可重用性角度更好地控制您的控件。为某些属性定义getter和setter,在attrs.xml中定义自定义属性,实现对初始化代码中的自定义属性的处理。公开一些自定义侦听器,如EventClickedListener或其他东西。
  9. 在此基础上添加一些支持控件。将所有内容包裹在ScrollView中,我使用ViewPager处理水平滑动并显示上一个/下一天/周/月。
  10. 鉴于几乎准备好的日期时间表,从中提取基类并开始处理其他时间表,如周和月。
  11. 然后继续改进你的控制,直到你和你的队友对结果感到满意为止。显然,你需要在每一步上不断测试,调试和修复你的控件,所以拥有一堆测试用具非常有用。

    当我使用标准的Calendar API时,我也遇到了一些问题,因为我正在考虑使用其他库,例如Joda Time,但这是另一个故事。