2

我想像在 iPhone 中一样创建时间轴

在此处输入图像描述

事件时间可以是 9.42,它应该开始在 9.30 的虚线下方绘制,并且距离 9.30 有多远。

我能想到的唯一方法是使用ScrollViewwithFrameLayout并以编程方式添加时间线。

<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 开始。

描述此事件的文本必须跨越单元格。

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

4

1 回答 1

2

最近碰到同样的问题。我从你的框架布局的想法开始,上面有一堆视图,但对性能和我必须做的大量工作来绘制和自定义,比如项目下方的网格,我并不满意。

所以我继续集成的一个解决方案是扩展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. 在此之上添加一些支持控件。将整个内容包裹在 a 中ScrollView,我使用 aViewPager来处理水平滑动并显示前一天/第二天/一周/一个月。
  10. 给定几乎准备好的一天时间线,从中提取基类并开始处理其他时间线,例如周和月的时间线。

然后继续改进你的控制,直到你和你的队友对结果感到满意。显然,您需要在每个步骤中不断地测试、调试和修复您的控件,因此拥有一堆测试用例非常有帮助。

当我处理周和月概览时,我在使用标准 Calendar API 时也遇到了一些问题,因此您可能会考虑使用其他库,例如 Joda Time,但那是另一回事了。

于 2013-08-23T10:45:15.430 回答