作者:邹峰立,微博:zrunker,邮箱:zrunker@yahoo.com,微信公众号:书客创作,个人平台:www.ibooker.cc。
书客创作
时间轴效果无论是移动端还是Web端,都是十分常见的功能之一,主要用来按照时间或相应的步骤来说明或展示相应的信息。在移动端实现时间轴效果的方式也非常多,那么今天就说说如何利用ExPandableListView来实现时间轴效果。
对于ExPandableListView基本使用方法,可以通过
【Android】ExpandableListView的使用这篇文章进行了解。
分析:从纵向来看整个时间轴被划分成左右两个部分,但是如果要使用ExPandableListView实现这样的效果,就无法通过左右两个部分进行分析了。因为ExPandableListView是二级列表。那么从横向来看,确实可以将其划分成二级列表的模式,例如可以将竖线之上的部分划分为一级列表,将竖线平行部分划分为二级列表,这样就可以将该时间轴按照ExPandableListView的思想来设计了。
一、首先是XML布局
1、在页面布局文件activity_timeline.xml中添加ExPandableListView控件。
<ExpandableListView
android:id="@+id/expandlist"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:cacheColorHint="#00000000"
android:divider="@null"
android:listSelector="@android:color/transparent"
android:scrollbars="none" />
2、设置一级列表布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white">
<TextView
android:id="@+id/tv_step"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:gravity="end"
android:text="@string/app_name"
android:textColor="#555"
android:textSize="16sp" />
<ImageView
android:id="@+id/img_dot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_margin="10dp"
android:layout_toEndOf="@id/tv_step"
android:layout_toRightOf="@id/tv_step"
android:contentDescription="@null"
android:src="@drawable/guide_dot_choose" />
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toEndOf="@id/img_dot"
android:layout_toRightOf="@id/img_dot"
android:text="@string/app_name"
android:textColor="@color/colorTitle"
android:textSize="16sp" />
</RelativeLayout>
一级列表布局效果图
3、二级列表布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:gravity="center_vertical">
<View
android:id="@+id/view_line"
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_marginLeft="95dp"
android:layout_marginStart="95dp"
android:background="#ccc" />
<TextView
android:id="@+id/tv_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="3dp"
android:layout_marginEnd="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginStart="10dp"
android:layout_marginTop="3dp"
android:lineSpacingExtra="3dp"
android:lines="1"
android:text="@string/hello_world"
android:textColor="#888" />
</LinearLayout>
二级列表布局效果图
二、设置列表数据对象
1、一级列表数据对象,一级列表数据对象类包含对应二级列表数据集。
public class TimeLineGroupData {
private String gtitle;
private String gstep;
/**
* 二级Item数据列表
**/
private List<TimeLineChildData> childList;
public String getGtitle() {
return gtitle;
}
public void setGtitle(String gtitle) {
this.gtitle = gtitle;
}
public String getGstep() {
return gstep;
}
public void setGstep(String gstep) {
this.gstep = gstep;
}
public List<TimeLineChildData> getChildList() {
return childList;
}
public void setChildList(List<TimeLineChildData> childList) {
this.childList = childList;
}
}
2、二级列表对象。
public class TimeLineChildData {
/**
* 描述信息
**/
private String desc;
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
三、自定义Adapter
自定义ExPandableListView的适配器需要继承BaseExpandableListAdapter 。并实现一级列表和二级列表的相关处理方法。
public class TimeLineExpAdapter extends BaseExpandableListAdapter {
private LayoutInflater inflater = null;
private List<TimeLineGroupData> groupList = new ArrayList<>();
/**
* 构造方法
*/
public TimeLineExpAdapter(Context context, List<TimeLineGroupData> group_list) {
this.groupList = group_list;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
// 刷新数据
public void flashData(List<TimeLineGroupData> datas) {
this.groupList = datas;
this.notifyDataSetChanged();
}
/**
* 返回一级Item总数
*/
@Override
public int getGroupCount() {
return groupList.size();
}
/**
* 返回二级Item总数
*/
@Override
public int getChildrenCount(int groupPosition) {
if (groupList.get(groupPosition).getChildList() == null) {
return 0;
} else {
return groupList.get(groupPosition).getChildList().size();
}
}
/**
* 获取一级Item内容
*/
@Override
public Object getGroup(int groupPosition) {
return groupList.get(groupPosition);
}
/**
* 获取二级Item内容
*/
@Override
public Object getChild(int groupPosition, int childPosition) {
return groupList.get(groupPosition).getChildList().get(childPosition);
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public boolean hasStableIds() {
return false;
}
// 一级列表
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
GroupViewHolder holder;
if (convertView == null) {
holder = new GroupViewHolder();
convertView = inflater.inflate(R.layout.activity_timeline_group_item, parent, false);
holder.stepTv = (TextView) convertView.findViewById(R.id.tv_step);
holder.titleTv = (TextView) convertView.findViewById(R.id.tv_title);
convertView.setTag(holder);
} else {
holder = (GroupViewHolder) convertView.getTag();
}
holder.titleTv.setText(groupList.get(groupPosition).getGstep());
holder.stepTv.setText(groupList.get(groupPosition).getGtitle());
return convertView;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
ChildViewHolder viewHolder;
TimeLineChildData entity = (TimeLineChildData) getChild(groupPosition, childPosition);
if (convertView != null) {
viewHolder = (ChildViewHolder) convertView.getTag();
} else {
viewHolder = new ChildViewHolder();
convertView = inflater.inflate(R.layout.activity_timeline_child_item, parent, false);
viewHolder.descTv = (TextView) convertView.findViewById(R.id.tv_desc);
convertView.setTag(viewHolder);
}
viewHolder.descTv.setText(entity.getDesc());
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return false;
}
private class GroupViewHolder {
TextView titleTv, stepTv;
}
private class ChildViewHolder {
TextView descTv;
}
}
四、Activity实现
public class TimeLineActivity extends AppCompatActivity {
private ExpandableListView expandlistView;
private TimeLineExpAdapter statusAdapter;
private List<TimeLineGroupData> groupList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timeline);
initView();
setListData();
setAdapter();
initExpandListView();
}
// 初始化控件
private void initView() {
expandlistView = (ExpandableListView) findViewById(R.id.expandlist);
}
/**
* 自定义setAdapter
*/
private void setAdapter() {
if (statusAdapter == null) {
statusAdapter = new TimeLineExpAdapter(this, groupList);
expandlistView.setAdapter(statusAdapter);
} else {
statusAdapter.flashData(groupList);
}
}
/**
* 初始化可拓展列表
*/
private void initExpandListView() {
expandlistView.setGroupIndicator(null); // 去掉默认带的箭头
expandlistView.setSelection(0);// 设置默认选中项
// 遍历所有group,将所有项设置成默认展开
int groupCount = expandlistView.getCount();
for (int i = 0; i < groupCount; i++) {
expandlistView.expandGroup(i);
}
expandlistView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
return true;
}
});
}
// 列表赋值
private List<TimeLineGroupData> setListData() {
if (groupList == null) {
groupList = new ArrayList<>();
// 一级列表数据
for (int i = 0; i < 8; i++) {
TimeLineGroupData timeLineGroupData = new TimeLineGroupData();
timeLineGroupData.setGtitle("第" + i + "步");
timeLineGroupData.setGstep("第" + i + "步的标题");
// 二级列表数据
ArrayList<TimeLineChildData> childDataList = new ArrayList<>();
for (int j = 0; j < 2; j++) {
TimeLineChildData timeLineChildData = new TimeLineChildData();
timeLineChildData.setDesc("第" + i + "步描述" + j + "实现时间轴效果");
childDataList.add(timeLineChildData);
}
timeLineGroupData.setChildList(childDataList);
groupList.add(timeLineGroupData);
}
}
return groupList;
}
}
到这里一个简单的时间轴效果就实现了,但是有几个地方需要注意:
注意1:要收到设置时间轴为展开状态。
// 遍历所有group,将所有项设置成默认展开
int groupCount = expandlistView.getCount();
for (int i = 0; i < groupCount; i++) {
expandlistView.expandGroup(i);
}
注意2:去掉默认带的箭头
expandlistView.setGroupIndicator(null);
微信公众号:书客创作
网友评论