Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/211.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
实现Android时间表日历的最佳方法_Android_Listview_Scrollview_Timeline - Fatal编程技术网

实现Android时间表日历的最佳方法

实现Android时间表日历的最佳方法,android,listview,scrollview,timeline,Android,Listview,Scrollview,Timeline,我想创建类似iPhone的时间线 事件时间可以是9.42,它应该在9.30的虚线下开始绘制,距离9.30的百分比 我能想到的唯一方法是将ScrollView与FrameLayout一起使用,并以编程方式添加时间线 <ScrollView android:id="@+id/scrollView1" android:layout_width="match_parent" android:layout_height="0dp" a

我想创建类似iPhone的时间线

事件时间可以是9.42,它应该在9.30的虚线下开始绘制,距离9.30的百分比

我能想到的唯一方法是将
ScrollView
FrameLayout
一起使用,并以编程方式添加时间线

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

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

有人能推荐我吗?
谢谢。

最近遇到了同样的问题。我从你的framelayout想法开始,上面有一堆视图,但我对性能和我必须做的大量工作不太满意,比如在项目下面绘制和自定义网格

所以我提出并集成了一个解决方案,就是扩展
视图
类,覆盖它的
onDraw
和相关方法,然后在那里绘制我需要的任何东西

在这种情况下,我对正在发生的事情以及我希望它看起来的样子有很大的控制权。不用说,我可以而且确实实现了一些性能改进,比如将底层网格缓存到位图中等等,这在处理布局和视图的组合这样的高级内容时是很难实现的

在任何情况下,您或任何有相同问题的人都可能希望从简单的内容开始,例如(代码在我的脑海中消失):

公共类MyDayTimeline扩展视图{
String[]timeMarkers;//时间字符串,比如“9.00am”之类的
Rect[]eventRects;//一组矩形,对应于您的事件
最终整数行数;
最终整数行高px;
最终int firstColumnWidthPx;
//..…构造函数、大小和绘制初始化、事件位置计算等等
@凌驾
受保护的void onDraw(画布){
drawLine(firstColumnWidthPx,0,firstColumnWidthPx,getMeasuredHeight(),delimeterLinesPaint);//在时间标记和其余控件空间之间绘制delimeter
对于(int i=1;i
乍一看,需要做的大量工作似乎是压倒性的,但事实并非如此,如果你先计划好需要做的事情,然后再去做。我是这样说的:

  • 首先在
    onDraw()
    覆盖中绘制一个简单的时间轴网格,所有尺寸和颜色都是硬编码的
  • 覆盖
    onMeasure()
    onSizeChanged()
    ,开始相应地更改大小控制字段。我用简单的尺寸来确定我在哪里获得所有可用的空间宽度,并大胆地要求
    24*rowHeightPx
    高度,而不管测量规格如何
  • 使用“canvas.drawText()”在时间网格中放置一组时间里程碑
  • 拿出一个结构来定义你的事件。我使用了开始和结束日期/时间、一些主题字符串和一组矩形。当控件的大小改变时,我会重新计算矩形,每个事件都应该使用矩形
  • onDraw()
    中实现事件绘制,并将先前定义的结构和位置计算放在适当的位置
  • 处理特定情况,如跨越几天的事件
  • onTouchEvent()
    或其他方法开始处理水龙头。添加一些日志以查看是否正确执行命中测试,如果需要,开始用高亮显示的颜色重新绘制事件帧等等
  • 从可重用性的角度使您的控制更好。为某些属性定义getter和setter,在
    attrs.xml
    中定义自定义属性,在初始化代码中实现对这些属性的处理。公开一些自定义侦听器,如EventClickedListener等
  • 在上面添加一些支持控件。在
    滚动视图
    中包装整个内容,我使用
    查看页面
    来处理水平滑动并显示上一天/下一天/周/月
  • 给定一个几乎准备就绪的日期时间线,从中提取基类并开始处理其他时间线,比如周和月时间线
  • 然后继续提高你的控制力,直到你和你的队友对结果满意为止。显然,您需要在每个步骤上不断地测试、调试和修复您的控件,因此拥有一堆测试用例是非常有用的

    我使用标准日历API时也遇到了一些问题,当我在进行周和月概述时,你可以考虑使用其他库,比如JoDaTime,但这是另一个故事。

    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);
            }
        }
    }