本章内容

现在原来越多的APP中,会习惯在类似朋友圈的列表旁边加上时间线,好吧,其实我们的也有,给大家看看怎么实现的


效果(项目实在是装不上模拟器,只能给个短一点的列表静态图了):

Android RequestBody 时间_控件

这个效果还不错吧,UI设计的确实挺好看的


我的做法是将这条时间线做成了一个自定义组合控件,这种有自身效果的控件,我建议是将它单独看成一个View,尽量不要用Item去控制它,也就是说不要将具体的控件都写在Item中,那样的话实在是太乱了。

我自定义了一个组合控件 LiveDynamicTimeLineView,先看XML:

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

    <View
        android:id="@+id/top"
        android:layout_width="match_parent"
        android:layout_height="10dp"/>

    <ImageView
        android:id="@+id/live_dynamic_time_line_start"
        android:layout_width="15dp"
        android:layout_height="15dp"
        android:src="@drawable/icon_point_of_time_2x" />

    <View
        android:id="@+id/v1"
        android:layout_width="1dp"
        android:layout_height="0dp"
        android:layout_gravity="center_horizontal"
        android:layout_weight="1"
        android:background="#dadada" />

    <View
        android:id="@+id/v2"
        android:layout_width="1dp"
        android:layout_height="16.5dp"
        android:layout_gravity="center_horizontal"
        android:background="#dadada" />

    <ImageView
        android:id="@+id/live_dynamic_time_line_middle"
        android:layout_width="7dp"
        android:layout_height="7dp"
        android:layout_gravity="center_horizontal"
        android:src="@drawable/icon_spot_2x" />

    <View
        android:id="@+id/v3"
        android:layout_width="1dp"
        android:layout_height="9.5dp"
        android:layout_gravity="center_horizontal"
        android:background="#dadada" />

    <View
        android:id="@+id/v4"
        android:layout_width="1dp"
        android:layout_height="0dp"
        android:layout_gravity="center_horizontal"
        android:layout_weight="1"
        android:background="#dadada" />

    <View
        android:id="@+id/v5"
        android:layout_width="1dp"
        android:layout_height="17dp"
        android:layout_gravity="center_horizontal"
        android:background="#dadada" />

    <ImageView
        android:id="@+id/live_dynamic_time_line_end"
        android:layout_width="4dp"
        android:layout_height="4dp"
        android:layout_gravity="center_horizontal"
        android:src="@drawable/icon_spot_2x" />

</LinearLayout>

首先,对于不同的条目,时间线的长短也是不一样的,所以这里的父布局我用了LinearLayout,其中主干部分 live_dynamic_time_line_start, live_dynamic_time_line_middle, live_dynamic_time_line_end分别代表了起始点,中间点,和结束点的3个控件,以及能够自适应的View:v1和v4,从布局中就可以看到它们的height是0dp,weight都是1,这两个权重控件是自适应Item高度的,但是如果只有这写还是不够的,没有办法实现上图中的效果,首先,可以从图中的效果可以看出每个时间线的红点都是相对应Item的时间头居中的,并且,每个Item是有留白的间距的,这里就要具体情况具体看了。
首先,可以看到XML中我有一个 id 是 top的View,这个控件是为了第一个Item需要距顶部留白,所以可以看到它是没有背景色的。
其次,在我显示的Item是图片或者视屏的时候,Item的时间头是有图片的,如果这里我不设置 v2 和 v3,那么效果,就一定是时间线中的红点紧紧地贴住Item的顶部,而不是现在这样居中左右,那样就会很难看了。首先我要显示的那些时间头的小图片是 26dp 高的,所以 v2(时间点上面的线)要比v3要长一点,因为不仅要保证时间点在图片的中间,还要算上Item之间的留白,v2的高度是 16.5dp,而v3的高度是9.5,live_dynamic_time_line_middle的高度是7dp,那么其实要看是不是居中可以这么算:16.5-10+7/2=10, 也即是中间时间点的中心在时间头图片的10dp处,这里我是偷了个懒,因为赶着上线没有将文字和图片这两种情况分开,只是做了个大概的效果,准确的高度其实应该是 v2 19.5dp才对,不过大家将就着看吧。
最后v4, v5也是一样的道理,v4是自适应高度的空间,v5是当最后一个Item时才会显示的,也是用来使时间点居中的间距控件。

LiveDynamicTimeLineView:

package com.xianrou.fresh.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import com.xianrou.fresh.R;

/**
 * Created by chenjiahuan on 16/5/11.
 */
public class LiveDynamicTimeLineView extends RelativeLayout {

    public static final int START = 1;
    public static final int MIDDLE = 2;
    public static final int END = 3;

    private View rootView, v1, v2, v3, v4, v5, top;

    private ImageView live_dynamic_time_line_start, live_dynamic_time_line_middle, live_dynamic_time_line_end;

    public LiveDynamicTimeLineView(Context context) {
        super(context);
        rootView = View.inflate(context, R.layout.live_dynamic_time_line, this);
    }

    public LiveDynamicTimeLineView(Context context, AttributeSet attrs) {
        super(context, attrs);
        rootView = View.inflate(context, R.layout.live_dynamic_time_line, this);
    }

    public LiveDynamicTimeLineView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        rootView = View.inflate(context, R.layout.live_dynamic_time_line, this);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        initView();
    }

    public void initView() {
        v1 = rootView.findViewById(R.id.v1);
        v2 = rootView.findViewById(R.id.v2);
        v3 = rootView.findViewById(R.id.v3);
        v4 = rootView.findViewById(R.id.v4);
        v5 = rootView.findViewById(R.id.v5);
        top = rootView.findViewById(R.id.top);
        live_dynamic_time_line_end = (ImageView) rootView.findViewById(R.id.live_dynamic_time_line_end);
        live_dynamic_time_line_start = (ImageView) rootView.findViewById(R.id.live_dynamic_time_line_start);
        live_dynamic_time_line_middle = (ImageView) rootView.findViewById(R.id.live_dynamic_time_line_middle);
    }

    ;

    public void show(int mode) {
        switch (mode) {
            case START:
                showStart();
                break;

            case MIDDLE:
                showMiddle();
                break;

            case END:
                showEnd();
                break;
        }
    }

    private void showEnd() {
        v1.setVisibility(View.GONE);
        v2.setVisibility(View.GONE);
        v3.setVisibility(View.GONE);
        v4.setVisibility(View.GONE);
        top.setVisibility(View.GONE);
        live_dynamic_time_line_start.setVisibility(View.GONE);
        live_dynamic_time_line_middle.setVisibility(View.GONE);

        v5.setVisibility(View.VISIBLE);
        live_dynamic_time_line_end.setVisibility(View.VISIBLE);
    }

    private void showMiddle() {
        v1.setVisibility(View.GONE);
        v5.setVisibility(View.GONE);
        top.setVisibility(View.GONE);
        live_dynamic_time_line_end.setVisibility(View.GONE);
        live_dynamic_time_line_start.setVisibility(View.GONE);

        v2.setVisibility(View.VISIBLE);
        v3.setVisibility(View.VISIBLE);
        v4.setVisibility(View.VISIBLE);
        live_dynamic_time_line_middle.setVisibility(View.VISIBLE);
    }

    private void showStart() {
        v2.setVisibility(View.GONE);
        v3.setVisibility(View.GONE);
        v4.setVisibility(View.GONE);
        v5.setVisibility(View.GONE);
        live_dynamic_time_line_end.setVisibility(View.GONE);
        live_dynamic_time_line_middle.setVisibility(View.GONE);

        v1.setVisibility(View.VISIBLE);
        top.setVisibility(View.VISIBLE);
        live_dynamic_time_line_start.setVisibility(View.VISIBLE);
    }

}

在使用的时候,只需要传入MODE,也就是你希望当前的时间线是什么状态的就行了。因为是项目的代码,这里就不贴代码了,有思路就行了。