web-dev-qa-db-ja.com

Googleのロケーション履歴のようなAndroidタイムラインビューを作成するには?

enter image description here

Googleロケーション履歴のようなユーザーインターフェースを設計したい。

14
Nilesh Rathore

RecyclerViewを使用して作業したアプリケーションに対して、このUIを複製する必要がありました。
各行は水平のLinearLayoutであり、アイコン、ライン、右側のビューが含まれます。線は背景が丸いFrameLayoutで、半透明の円はViewsです。
行間にスペースがないため、線の単一部分が結合されているように見えます。
アイテムのレイアウトは次のようになります。

<LinearLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:orientation="horizontal"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content">

    <!-- the circular icon on the left -->
    <ImageView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:src="@drawable/ic_place"
        Android:tint="@Android:color/white"
        Android:layout_marginRight="24dp"
        Android:padding="4dp"
        Android:background="@drawable/circle_bg"/>

    <!-- the blue line -->
    <FrameLayout
        Android:layout_width="15dp"
        Android:layout_height="match_parent"
        Android:padding="2dp"
        Android:id="@+id/item_line">

        <!-- the semi transparent circle on the line -->
        <View
            Android:layout_width="11dp"
            Android:layout_height="11dp"
            Android:background="@drawable/circle"/>

    </FrameLayout>

    <!-- views at the right of the blue line -->
    <LinearLayout
        Android:layout_width="0dp"
        Android:layout_weight="1"
        Android:layout_height="wrap_content"
        Android:orientation="vertical"
        Android:paddingLeft="24dp"
        Android:paddingBottom="32dp"
        Android:clickable="true"
        Android:background="?android:attr/selectableItemBackground">

        <TextView
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:singleLine="true"
            Android:ellipsize="end"
            Android:textAppearance="@style/TextAppearance.AppCompat.Title"
            Android:id="@+id/item_title"/>

        <TextView
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:id="@+id/item_subtitle"/>

        <!-- other views -->

    </LinearLayout>
</LinearLayout>

上のキャップ、中央のキャップ、最後のキャップの線のキャップを異なる方法でレンダリングする便利な方法は、Adapterで位置関連のitemViewTypesを使用することです。

private static final int VIEW_TYPE_TOP = 0;
private static final int VIEW_TYPE_MIDDLE = 1;
private static final int VIEW_TYPE_BOTTOM = 2;
private List<Item> mItems;

// ...

class ViewHolder extends RecyclerView.ViewHolder {

    TextView mItemTitle;
    TextView mItemSubtitle;
    FrameLayout mItemLine;

    public ViewHolder(View itemView) {
        super(itemView);
        mItemTitle = (TextView) itemView.findViewById(R.id.item_title);
        mItemSubtitle = (TextView) itemView.findViewById(R.id.item_subtitle);
        mItemLine = (FrameLayout) itemView.findViewById(R.id.item_line);
    }
}

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
    Item item = mItems.get(position);
    // Populate views...
    switch(holder.getItemViewType()) {
        case VIEW_TYPE_TOP:
            // The top of the line has to be rounded
            holder.mItemLine.setBackground(R.drawable.line_bg_top);
            break;
        case VIEW_TYPE_MIDDLE:
            // Only the color could be enough
            // but a drawable can be used to make the cap rounded also here
            holder.mItemLine.setBackground(R.drawable.line_bg_middle);
            break;
        case VIEW_TYPE_BOTTOM:
            holder.mItemLine.setBackground(R.drawable.line_bg_bottom);
            break;
    }
}

@Override
public int getItemViewType(int position) {
    if(position == 0) {
        return VIEW_TYPE_TOP;
    else if(position == mItems.size() - 1) {
        return VIEW_TYPE_BOTTOM;
    }
    return VIEW_TYPE_MIDDLE;
}

背景のドロアブルは次のように定義できます。

<!-- line_bg_top.xml -->
<shape xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <solid Android:color="@color/colorPrimary"/>
    <corners
        Android:topLeftRadius="15dp"
        Android:topRightRadius="15dp"/>
    <!-- this has to be at least half of line FrameLayout's
         width to appear completely rounded -->
</shape>

<!-- line_bg_middle.xml -->
<shape xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <solid Android:color="@color/colorPrimary"/>
</shape>

<!-- line_bg_bottom.xml -->
<shape xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <solid Android:color="@color/colorPrimary"/>
    <corners
        Android:bottomLeftRadius="15dp"
        Android:bottomRightRadius="15dp"/>
</shape>

もちろん、ListViewを使用することもできます。また、ステップが常に数個であることがわかっている場合は、単純な垂直LinearLayoutで十分です。

悲しいことに、Google Maps Androidアプリはオープンソースではありません。公式な方法を知るのはそれほど簡単ではありません... Material Designの解釈!

20
Umbo