#个人需求
最近项目有个时间轴的需求,如下图。(数据不同,背景不同)
#需求实现
##先扒一扒demo中用到的工具类。
//日期格式化 20170606 -> 2017.06.06
public class TimeFormat {
public static String format(String format, String time) {
String result = "";
SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
try {
Date date = df.parse(time);
SimpleDateFormat df1 = new SimpleDateFormat(format);
result = df1.format(date);
} catch (ParseException e) {
e.printStackTrace();
}
return result;
}
}
demo如此,实际中可能是系统时间毫秒或者秒,所以你可能需要这个
/**
* 日期转换 wen
*/
public class DateUtil {
private static long duration;
/**
* 系统时间转换为年月日
* @param timestamp
* @return
*/
public static String timestamp2y(long timestamp){
SimpleDateFormat format = new SimpleDateFormat("yyyy");
return format.format(timestamp*1000);
}
public static String timestamp2ymd(long timestamp){
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
return format.format(timestamp*1000);
}
public static String toymdhms(long timestamp){
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return format.format(timestamp*1000);
}
}
/**
* 对时间进行排序,在实际开发中最好要后台给按时间顺序排序好的数据
*/
public class TimeComparator implements Comparator<TimeData> {
@Override
public int compare(TimeData td1, TimeData td2) {
return td2.getPosttime().compareTo(td1.getPosttime());
}
}
/**
* dp和px转换工具类
*/
public class DensityUtil {
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density; // 获取手机的屏幕的密度
return (int) (dpValue * scale + 0.5f);
}
/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
*/
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
}
##然后就是对数据的bean类保存了 (实际开发最好私有化变量 提供get set方法,这里demo简单化)
public class TimeData {
public String posttime;
public String title;
public TimeData(String posttime,String title) {
this.title = title;
this.posttime = posttime;
}
}
##最后就是主要的代码编写了
//main里面就是数据的初始化,时间排序,adapter设置(xml不贴了,很简单)
public class MainActivity extends AppCompatActivity {
//存储列表数据
List<TimeData> list = new ArrayList<>();
TimeAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView rlView = (RecyclerView) findViewById(R.id.activity_rlview);
//初始化数据
initData();
// 将数据按照时间排序
TimeComparator comparator = new TimeComparator();
Collections.sort(list, comparator);
// recyclerview绑定适配器
rlView.setLayoutManager(new LinearLayoutManager(this));
adapter = new TimeAdapter(this, list);
rlView.setAdapter(adapter);
}
private void initData() {
list.add(new TimeData("20170710", "我是第一个数据"));
list.add(new TimeData("20140709", "我是多数据模块第一个数据"));
list.add(new TimeData("20140709", "我是多数据模块第二个数据"));
list.add(new TimeData("20140708", "我是多数据模块第三个数据"));
list.add(new TimeData("20140709", "我是多数据模块第一个数据"));
list.add(new TimeData("20140708", "我是多数据模块第二个数据"));
list.add(new TimeData("20140708", "我是多数据模块第三个数据"));
list.add(new TimeData("20140706", "我是最后一个数据"));
}
}
//适配器代码编写 最主要的就是逻辑的处理
public class TimeAdapter extends RecyclerView.Adapter{
private MainActivity activity;
private List<TimeData> data;
public TimeAdapter(MainActivity mainActivity, List<TimeData> list) {
this.activity = mainActivity;
this.data = list;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.tiemview, parent, false));
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((ViewHolder) holder).setPosition(position);
}
@Override
public int getItemCount() {
return data.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
private TextView txtDateTime;
private TextView txt_date_title;
private RelativeLayout rlTitle;
private View vLine;
private int position;
private TimeData timeData;
public ViewHolder(View itemView) {
super(itemView);
rlTitle = (RelativeLayout) itemView.findViewById(R.id.rl_title);
vLine = itemView.findViewById(R.id.v_line);
txtDateTime = (TextView) itemView.findViewById(R.id.txt_date_time);
txt_date_title = (TextView) itemView.findViewById(R.id.txt_date_title);
}
public void setPosition(int position) {
this.position = position;
timeData = data.get(position);
//时间轴竖线的layoutParams,用来动态的添加竖线
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) vLine.getLayoutParams();
//position等于0的处理
if (position == 0) {
//数据个数必须大于等于2,要不对于时间的判断会有越界危险
if (data.size() >= 2) {
if (!timeData.getPosttime().equals(data.get(position + 1).getPosttime())) {
txt_date_title.setBackgroundResource(R.drawable.message_sys_bgfirst);
layoutParams.setMargins(DensityUtil.dip2px(vLine.getContext(), 20), DensityUtil.dip2px(vLine.getContext(), 15), 0, 0);
} else {
txt_date_title.setBackgroundResource(R.drawable.message_sys_bgtop);
layoutParams.setMargins(DensityUtil.dip2px(vLine.getContext(), 20), DensityUtil.dip2px(vLine.getContext(), 15), 0, 0);
}
} else {
txt_date_title.setBackgroundResource(R.drawable.message_sys_bgfirst);
//动态的代码设置距离上面的边距,只有第一条才有上边距
layoutParams.setMargins(DensityUtil.dip2px(vLine.getContext(), 20), DensityUtil.dip2px(vLine.getContext(), 15), 0, 0);
}
rlTitle.setVisibility(View.VISIBLE);
txtDateTime.setText(TimeFormat.format("yyyy.MM.dd", timeData.getPosttime()));
layoutParams.addRule(RelativeLayout.ALIGN_TOP, R.id.rl_title);
layoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.txt_date_title);
} else if (position < data.size() - 1) {
if (timeData.getPosttime().equals(data.get(position - 1).getPosttime())) {
if (timeData.getPosttime().equals(data.get(position + 1).getPosttime())) {
rlTitle.setVisibility(View.GONE);
layoutParams.setMargins(DensityUtil.dip2px(vLine.getContext(), 20), DensityUtil.dip2px(vLine.getContext(), 0), 0, 0);
txt_date_title.setBackgroundResource(R.drawable.message_sys_bgcenter);
layoutParams.addRule(RelativeLayout.ALIGN_TOP, R.id.txt_date_title);
layoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.txt_date_title);
} else {
rlTitle.setVisibility(View.GONE);
txt_date_title.setBackgroundResource(R.drawable.message_sys_bgbot);
layoutParams.addRule(RelativeLayout.ALIGN_TOP, R.id.txt_date_title);
layoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.txt_date_title);
}
} else {
if (!timeData.getPosttime().equals(data.get(position + 1).getPosttime())) {
txt_date_title.setBackgroundResource(R.drawable.message_sys_bgfirst);
} else {
txt_date_title.setBackgroundResource(R.drawable.message_sys_bgtop);
}
layoutParams.setMargins(DensityUtil.dip2px(vLine.getContext(), 20), DensityUtil.dip2px(vLine.getContext(), 0), 0, 0);
rlTitle.setVisibility(View.VISIBLE);
txtDateTime.setText(TimeFormat.format("yyyy.MM.dd", timeData.getPosttime()));
layoutParams.addRule(RelativeLayout.ALIGN_TOP, R.id.rl_title);
layoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.txt_date_title);
}
} else {
if (!timeData.getPosttime().equals(data.get(position - 1).getPosttime())) {
txt_date_title.setBackgroundResource(R.drawable.message_sys_bgfirst);
rlTitle.setVisibility(View.VISIBLE);
txtDateTime.setText(TimeFormat.format("yyyy.MM.dd", timeData.getPosttime()));
layoutParams.setMargins(DensityUtil.dip2px(vLine.getContext(), 20), DensityUtil.dip2px(vLine.getContext(), 0), 0, 0);
layoutParams.addRule(RelativeLayout.ALIGN_TOP, R.id.rl_title);
layoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.txt_date_title);
} else {
rlTitle.setVisibility(View.GONE);
txt_date_title.setBackgroundResource(R.drawable.message_sys_bgbot);
txtDateTime.setText(TimeFormat.format("yyyy.MM.dd", timeData.getPosttime()));
layoutParams.setMargins(DensityUtil.dip2px(vLine.getContext(), 20), DensityUtil.dip2px(vLine.getContext(), 0), 0, 0);
layoutParams.addRule(RelativeLayout.ALIGN_TOP, R.id.txt_date_title);
layoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.txt_date_title);
}
}
vLine.setLayoutParams(layoutParams);
txt_date_title.setText(timeData.getTitle());
}
}
}
##条目的xml布局还是贴一下吧
<?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">
<View
android:id="@+id/v_line"
android:layout_width="0.5dp"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:background="#666666" />
<RelativeLayout
android:id="@+id/rl_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="4dp"
android:src="@mipmap/piccirclegreen" />
<TextView
android:id="@+id/txt_date_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="30dp"
android:text="2015.1.02"
android:textSize="12dp" />
</RelativeLayout>
<TextView
android:id="@+id/txt_date_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/rl_title"
android:padding="10dp"
android:layout_marginLeft="30dp"
android:text="您发布的帖子标题已被取消置顶"
android:textSize="15sp" />
</RelativeLayout>
##背景
文中的共有四个背景,其实就是四个shape。
代码已经放在这里了,欢迎查看,我写的不好的或者不清楚的也请指出。
https://github.com/loveAndroidAndroid/TimeLine