本章内容
现在原来越多的APP中,会习惯在类似朋友圈的列表旁边加上时间线,好吧,其实我们的也有,给大家看看怎么实现的
效果(项目实在是装不上模拟器,只能给个短一点的列表静态图了):
这个效果还不错吧,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,也就是你希望当前的时间线是什么状态的就行了。因为是项目的代码,这里就不贴代码了,有思路就行了。