Как создать недельное представление календаря для приложения Android Honeycomb?

Я работаю над приложением Android (v3.0), которое требует сопоставления еженедельного макета календаря, найденного в Календаре Google:

Google Calendar Weekly Layout

События будут основываться на внешних запросах через API календаря Google (у меня уже есть эта часть работы). Используя API, я могу получить список событий за неделю, причем каждое событие имеет начало и конец datetime. Я хотел бы использовать эти данные для отображения запланированных событий пользователям приложения в представлении, аналогичном приведенному выше.

Вот что я до сих пор:

My Prototype Calendar View

Ниже представлен XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="800dp"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Calendar Title"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <RelativeLayout
        android:id="@+id/relativeLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <LinearLayout
            android:id="@+id/linearLayout1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true" >

            <TextView
                android:id="@+id/textView2"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="" />

            <TextView
                android:id="@+id/textView3"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="2"
                android:gravity="center"
                android:text="Sunday" />

            <TextView
                android:id="@+id/textView4"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="2"
                android:gravity="center"
                android:text="Monday" />

            <TextView
                android:id="@+id/textView5"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="2"
                android:gravity="center"
                android:text="Tuesday" />

            <TextView
                android:id="@+id/textView6"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="2"
                android:gravity="center"
                android:text="Wednesday" />

            <TextView
                android:id="@+id/textView7"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="2"
                android:gravity="center"
                android:text="Thursday" />

            <TextView
                android:id="@+id/textView8"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="2"
                android:gravity="center"
                android:text="Friday" />

            <TextView
                android:id="@+id/textView9"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="2"
                android:gravity="center"
                android:text="Saturday" />
        </LinearLayout>
    </RelativeLayout>

    <ScrollView
        android:id="@+id/scrollView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="0dp"
        android:scrollbars="none" >"

        <RelativeLayout
            android:id="@+id/relativeLayout242"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="0dp" >


            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="0dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="40dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="80dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="120dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="160dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="200dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="240dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="280dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="320dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="360dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="400dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="440dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="480dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="520dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="560dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="600dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="640dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="680dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="720dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="760dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="800dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="840dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="880dp"/>
            <View android:background="#aaa" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="920dp"/>

            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="20dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="60dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="100dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="140dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="180dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="220dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="260dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="300dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="340dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="380dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="420dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="460dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="500dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="540dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="580dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="620dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="660dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="700dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="740dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="780dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="820dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="860dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="900dp"/>
            <View android:background="#777" android:layout_width = "fill_parent" android:layout_height="1dp" android:layout_marginTop="940dp"/>

            <LinearLayout
                android:id="@+id/linearLayout2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="0dp" >

                <RelativeLayout
                    android:id="@+id/relativeLayout2"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:padding="0dp" >

                    <View android:background="#aaa" android:layout_width = "1dp" android:layout_height="fill_parent" android:layout_alignParentRight="true"/>

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="0dp"
                        android:gravity="center"
                        android:text="12am" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="40dp"
                        android:gravity="center"
                        android:text="1am" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="80dp"
                        android:gravity="center"
                        android:text="2am" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="120dp"
                        android:gravity="center"
                        android:text="3am" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="160dp"
                        android:gravity="center"
                        android:text="4am" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="200dp"
                        android:gravity="center"
                        android:text="5am" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="240dp"
                        android:gravity="center"
                        android:text="6am" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="280dp"
                        android:gravity="center"
                        android:text="7am" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="320dp"
                        android:gravity="center"
                        android:text="8am" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="360dp"
                        android:gravity="center"
                        android:text="9am" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="400dp"
                        android:gravity="center"
                        android:text="10am" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="440dp"
                        android:gravity="center"
                        android:text="11am" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="480dp"
                        android:gravity="center"
                        android:text="12pm" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="520dp"
                        android:gravity="center"
                        android:text="1pm" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="560dp"
                        android:gravity="center"
                        android:text="2pm" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="600dp"
                        android:gravity="center"
                        android:text="3pm" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="640dp"
                        android:gravity="center"
                        android:text="4pm" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="680dp"
                        android:gravity="center"
                        android:text="5pm" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="720dp"
                        android:gravity="center"
                        android:text="6pm" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="760dp"
                        android:gravity="center"
                        android:text="7pm" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="800dp"
                        android:gravity="center"
                        android:text="8pm" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="840dp"
                        android:gravity="center"
                        android:text="9pm" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="880dp"
                        android:gravity="center"
                        android:text="10pm" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="match_parent"
                        android:layout_height="40dp"
                        android:layout_marginTop="920dp"
                        android:gravity="center|top"
                        android:text="11pm" />
                </RelativeLayout>

                <RelativeLayout
                    android:id="@+id/relativeLayout3"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="14"
                    android:padding="0dp" >

                    <LinearLayout
                        android:id="@+id/linearLayout3"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_alignParentLeft="true"
                        android:layout_alignParentRight="true"
                        android:layout_alignParentTop="true"
                        android:padding="0dp" >

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

                            <View android:background="#00f" android:layout_width = "fill_parent" android:layout_height="180dp" android:layout_marginTop="180dp"/>

                            <Button
                                android:id="@+id/button1"
                                android:layout_width="fill_parent"
                                android:layout_height="180dp"
                                android:layout_marginTop="180dp"
                                android:text="Some Event" />

                        </RelativeLayout>

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

                            <View android:background="#00f" android:layout_width = "fill_parent" android:layout_height="180dp" android:layout_marginTop="280dp"/>

                            <Button
                                android:id="@+id/button1"
                                android:layout_width="fill_parent"
                                android:layout_height="180dp"
                                android:layout_marginTop="280dp"
                                android:text="Some Event" />

                        </RelativeLayout>

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

                            <View android:background="#00f" android:layout_width = "fill_parent" android:layout_height="60dp" android:layout_marginTop="40dp"/>

                            <Button
                                android:id="@+id/button1"
                                android:layout_width="fill_parent"
                                android:layout_height="60dp"
                                android:layout_marginTop="40dp"
                                android:text="Some Event" />

                        </RelativeLayout>

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

                            <View android:background="#00f" android:layout_width = "fill_parent" android:layout_height="90dp" android:layout_marginTop="60dp"/>

                            <Button
                                android:id="@+id/button1"
                                android:layout_width="fill_parent"
                                android:layout_height="90dp"
                                android:layout_marginTop="60dp"
                                android:text="Some Event" />

                            <View android:background="#00f" android:layout_width = "fill_parent" android:layout_height="120dp" android:layout_marginTop="340dp"/>

                            <Button
                                android:id="@+id/button1"
                                android:layout_width="fill_parent"
                                android:layout_height="120dp"
                                android:layout_marginTop="340dp"
                                android:text="Some Event" />

                        </RelativeLayout>

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

                            <View android:background="#00f" android:layout_width = "fill_parent" android:layout_height="180dp" android:layout_marginTop="380dp"/>

                            <Button
                                android:id="@+id/button1"
                                android:layout_width="fill_parent"
                                android:layout_height="180dp"
                                android:layout_marginTop="380dp"
                                android:text="Some Event" />

                        </RelativeLayout>

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

                            <View android:background="#00f" android:layout_width = "fill_parent" android:layout_height="180dp" android:layout_marginTop="480dp"/>

                            <Button
                                android:id="@+id/button1"
                                android:layout_width="fill_parent"
                                android:layout_height="180dp"
                                android:layout_marginTop="480dp"
                                android:text="Some Event" />

                        </RelativeLayout>

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

                            <View android:background="#00f" android:layout_width = "fill_parent" android:layout_height="180dp" android:layout_marginTop="340dp"/>

                            <Button
                                android:id="@+id/button1"
                                android:layout_width="fill_parent"
                                android:layout_height="180dp"
                                android:layout_marginTop="340dp"
                                android:text="Some Event" />

                        </RelativeLayout>           

                    </LinearLayout>
                </RelativeLayout>
            </LinearLayout>
        </RelativeLayout>
    </ScrollView>

</LinearLayout>

Мой подход состоял в том, чтобы сделать 40dp равным 1 часу времени. Таким образом, всякий раз, когда я хотел бы добавить событие продолжительностью 1,5 часа, я сделаю кнопку 60dp, которую я разместим в том месте, где начинается время (12am = 0dp сверху, 1pm = 40dp сверху, 2pm = 80d сверху и т.д.).

Мои вопросы:

  • Есть ли лучший способ сделать это?
  • Как я могу преобразовать свой XML в автономное представление, которое можно было бы добавить в любой проект Android? (Я планирую, возможно, сделать сообщение в блоге о конечном продукте)

Спасибо!

Ответы

Ответ 1

В итоге я пришел к аналогичному подходу к моему оригинальному сообщению. Я создал прокрутку с линейным расположением внутри нее. Затем я добавил семь относительных макетов к линейной компоновке. Каждый из относительных макетов - один день. Я убедился, что высоты этих макетов равны количеству минут в день. Это сделало бы 1 час = 60 минут = 60 дп, что облегчит измерение высот событий. Для событий я создал настраиваемое представление, которое может отображать время начала и окончания события, а также заголовок события. События были добавлены к относительным макетам с свойством layout_marginTop, значение которого равно начальному времени события в минутах от начала дня. Казалось, это работает нормально.

Здесь предварительный просмотр того, что это выглядело следующим образом:

Calendar preview

Здесь XML-макет: http://pastebin.com/jT4wQxeb

Код слишком длинный, чтобы вписаться в ответ.

Примечание: calendar_zebra - это просто макет высотой 60 * 24 = 1440dp с горизонтальной высотой 1 dp View с твердым серым фоном, размещенным каждые 60 дп. Каждый из них представляет маркер в течение часа.

Ответ 2

1. Вот что я выяснил из источника Calendar

Он создает настраиваемый вид (DayView для повестки дня в день) для всего макета в вашем xml.

Затем он рисует холст, используя прямоугольник и текст, как то, что вы можете видеть в приложении, когда вызывается onDraw().

Вид реализует OnClickListener и OnLongClickListener для события. Когда вы нажимаете на холст, он переносит позицию вашего клика в Событие с соответствующими датами и временем (поэтому он вычисляет множество связанных размеров для события, поля, события целого дня, когда вызывается переопределение onSizeChanged()), а затем запускает Если существует такое Событие, в противном случае создается новое событие.

2. Вам нужно создать класс extends View, скажем DayView, тогда вы должны добавить его в attrs.xml

<resources>
  <declare-styleable name="DayView">
  </declare-styleable>
</resources>

Затем вы можете использовать его как тэг xml в макете с вашим именем пакета. как здесь:

<xxxxxxx.DayView
       android:layout_height="wrap_content"
       android:layout_width="match_parent"
       android:id="@id/ui_schedule_dayview">

Здесь вы можете найти образец для этого