前言
在Android开发中,时间轴的 UI非常常见,如下图:
储备知识:
1.自定义view基础
2.RecyclerView的使用
3.自定义RecyclerView.ItemDecoration
具体实现
1.最终效果如下:
2.实现思路
- 使用RecyclerView,自定义RecyclerView.ItemDecoration
- 复习ItemDecoration中getItemOffsets()方法,重写onDraw()方法
- 实现RecyclerView.Adapter,绑定数据
3.详细设计
4.具体实现
引入RecyclerView依赖包
1
2
3
4dependencies {
..........
api 'com.android.support:recyclerview-v7:28.0.0'
}在布局文件中使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="horizontal"
/>
</RelativeLayout>设置item布局
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<TextView
android:id="@+id/item_title"
android:text="New Text"
android:textSize="15sp"
android:layout_marginLeft="30dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Text"
android:layout_marginLeft="30dp"
android:textSize="15sp"
android:id="@+id/item_text"
android:layout_below="@+id/item_title"
/>
</LinearLayout>实现RecyclerView.Adapter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52public class MyAdapter extends RecyclerView.Adapter {
private LayoutInflater inflater;
private ArrayList<HashMap<String,Object>> listitem;
//构造函数,传入数据
public MyAdapter(Context context,ArrayList<HashMap<String, Object>> listitem) {
this.inflater = LayoutInflater.from(context);
this.listitem = listitem;
}
class ViewHolder extends RecyclerView.ViewHolder{
private TextView title,text;
public ViewHolder(@NonNull View itemView) {
super(itemView);
title = itemView.findViewById(R.id.item_title);
text = itemView.findViewById(R.id.item_text);
}
public TextView getTitle() {
return title;
}
public TextView getText() {
return text;
}
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
return new ViewHolder(inflater.inflate(R.layout.list_cell,null));
//绑定item布局
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
//绑定数据到ViewHolder
ViewHolder vh = (ViewHolder) viewHolder;
vh.title.setText((CharSequence) listitem.get(i).get("ItemTitle"));
vh.text.setText((CharSequence) listitem.get(i).get("ItemText"));
}
@Override
public int getItemCount() {
return listitem.size();
}
}自定义RecyclerView.ItemDecoration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150public class DividerItemDecoration extends RecyclerView.ItemDecoration {
//轴点画笔
private final Paint mPaint;
//时分画笔
private final Paint mPaint1;
//年月画笔
private final Paint mPaint2;
//itemView 左 上 偏移量
private int itemView_leftinterval;
private int itemView_topintervarl;
//轴点半径
private int circle_radius;
private final Bitmap mIcon;
//在构造函数里初始化需要属性
public DividerItemDecoration(Context context){
mPaint = new Paint();
mPaint.setColor(Color.RED);//设置画笔颜色为红色
mPaint1 = new Paint();
mPaint1.setColor(Color.BLUE);
mPaint1.setTextSize(30);//设置绘制字体大小
mPaint2 = new Paint();
mPaint2.setColor(Color.BLUE);
mPaint2.setTextSize(15);
itemView_leftinterval = 200; //左偏移长度200
itemView_topintervarl = 50; //上偏移长度50
circle_radius = 10;//轴点半径为10
mIcon = BitmapFactory.decodeResource(context.getResources(),R.mipmap.logo);
}
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
//设置itemview的左上偏移量,即为onDraw可绘制的区域
outRect.set(itemView_leftinterval,itemView_topintervarl,0,0);
}
@Override
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDraw(c, parent, state);
//获取RecyclerView的Child的个数
int childCount = parent.getChildCount();
//遍历每个item,分别获取他们的位置信息,然后在绘制对应的分割线
for (int i=0;i<childCount;i++){
View view = parent.getChildAt(i);//获取每个item对象
/**
* 绘制轴点
*/
// 轴点 = 圆 = 圆心(x,y)
float centerX = view.getLeft() - itemView_leftinterval/3;
float centerY = view.getTop() - itemView_topintervarl+(itemView_topintervarl+view.getHeight()/2);
// 绘制轴点圆
//c.drawCircle(centerX,centerY,circle_radius,mPaint);
c.drawBitmap(mIcon,centerX-circle_radius,centerY-circle_radius,mPaint);
/**
* 绘制上半轴线
*/
// 上端点坐标(x,y)
float upLine_up_x = centerX;
float upLine_up_y =view.getTop()-itemView_topintervarl;
// 下端点坐标(x,y)
float upLine_down_x = centerX;
float upLine_down_y = centerY-circle_radius;
c.drawLine(upLine_up_x,upLine_up_y,upLine_down_x,upLine_down_y,mPaint);//绘制下半轴线
/**
* 绘制下半轴线
*/
// 上端点坐标(x,y)
float bottomLine_up_x = centerX;
float bottom_up_y = centerY + circle_radius;
// 下端点坐标(x,y)
float bottomLine_bottom_x = centerX;
float bottomLine_bottom_y = view.getBottom();
//绘制下半部轴线
c.drawLine(bottomLine_up_x, bottom_up_y, bottomLine_bottom_x, bottomLine_bottom_y, mPaint);
/**
* 绘制左边时间文本
*/
int index = parent.getChildAdapterPosition(view);
//绘制时间文本起始位置
float Text_x = view.getLeft()-itemView_leftinterval*5/6;
float Text_y = upLine_down_y;
//根据item位置设置时间
switch (index){
case 0:
//设置绘制日期
c.drawText("13:40",Text_x,Text_y,mPaint1);
c.drawText("2018.4.03",Text_x+5,Text_y+20,mPaint2);
break;
case 1:
//设置绘制日期
c.drawText("13:40",Text_x,Text_y,mPaint1);
c.drawText("2018.4.03",Text_x+5,Text_y+20,mPaint2);
break;
case 2:
//设置绘制日期
c.drawText("13:40",Text_x,Text_y,mPaint1);
c.drawText("2018.4.03",Text_x+5,Text_y+20,mPaint2);
break;
case 3:
//设置绘制日期
c.drawText("13:40",Text_x,Text_y,mPaint1);
c.drawText("2018.4.03",Text_x+5,Text_y+20,mPaint2);
break;
case 4:
//设置绘制日期
c.drawText("13:40",Text_x,Text_y,mPaint1);
c.drawText("2018.4.03",Text_x+5,Text_y+20,mPaint2);
break;
case 5:
//设置绘制日期
c.drawText("13:40",Text_x,Text_y,mPaint1);
c.drawText("2018.4.03",Text_x+5,Text_y+20,mPaint2);
break;
default:
c.drawText("已签收",Text_x,Text_y,mPaint1);
}
}
}
}初始化数据,绑定RecyclerView
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60public class MainActivity extends AppCompatActivity {
private ArrayList<HashMap<String, Object>> itemlist;
private RecyclerView rl;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();
}
private void initData() {
itemlist = new ArrayList<HashMap<String, Object>>();
HashMap<String, Object> map1 = new HashMap<String, Object>();
HashMap<String, Object> map2 = new HashMap<String, Object>();
HashMap<String, Object> map3 = new HashMap<String, Object>();
HashMap<String, Object> map4 = new HashMap<String, Object>();
HashMap<String, Object> map5 = new HashMap<String, Object>();
HashMap<String, Object> map6 = new HashMap<String, Object>();
map1.put("ItemTitle", "中国广州公司已发出");
map1.put("ItemText", "发件人:妙卡迪文化公司");
itemlist.add(map1);
map2.put("ItemTitle", "国际顺丰已收入");
map2.put("ItemText", "等待中转");
itemlist.add(map2);
map3.put("ItemTitle", "国际顺丰转件中");
map3.put("ItemText", "下一站中国");
itemlist.add(map3);
map4.put("ItemTitle", "中国顺丰已收入");
map4.put("ItemText", "下一站江苏理工大学");
itemlist.add(map4);
map5.put("ItemTitle", "中国顺丰派件中");
map5.put("ItemText", "等待派件");
itemlist.add(map5);
map6.put("ItemTitle", "江苏理工大学已签收");
map6.put("ItemText", "收件人:darryrzhong");
itemlist.add(map6);
}
private void initView() {
rl = findViewById(R.id.my_recycler_view);
LinearLayoutManager manager = new LinearLayoutManager(this);
rl.setLayoutManager(manager);
//当知道Adapter内Item的改变不会影响RecyclerView宽高的时候,可以设置为true让RecyclerView避免重新计算大小。
rl.setHasFixedSize(true);
rl.addItemDecoration(new DividerItemDecoration(this));//设置自定义分割线
MyAdapter adapter = new MyAdapter(this,itemlist);
rl.setAdapter(adapter);
}
}
至此,自定义RecyclerView就实现完成了.
参考文章:
欢迎关注作者darryrzhong,更多干货等你来拿哟.
请赏个小红心!因为你的鼓励是我写作的最大动力!
更多精彩文章请关注