android时间轴(TimeLine)(recyclerView实现)

#个人需求
最近项目有个时间轴的需求,如下图。(数据不同,背景不同)
这里写图片描述

#需求实现

##先扒一扒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

  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Python可以使用各种库和框架来实现时间轴,例如: 1. 使用Matplotlib库来绘制时间轴图表,可以使用plot()函数来绘制数据点,使用axhline()函数来绘制时间轴线。 2. 使用Bokeh库来创建交互式时间轴,可以使用TimeSeries()函数来绘制时间序列数据,使用DatetimeTickFormatter()函数来格式化时间轴标签。 3. 使用Django框架来创建Web应用程序,可以使用Django的模板语言来渲染时间轴模板,使用Django的视图函数来处理时间轴数据。 以上是一些常见的Python实现时间轴的方法,具体实现方式可以根据具体需求和技术水平来选择。 ### 回答2: 在Python中实现时间轴可以有不同的方法,以下是其中一种较为简单的方式: 1. 首先需要安装pandas和matplotlib库,可以使用pip命令进行安装。 2. 导入所需库 ```python import pandas as pd import matplotlib.pyplot as plt ``` 3. 创建数据框(dataframe)并在其中添加时间和事件数据。时间可以使用python datetime模块或者pandas.to_datetime()方法来转换为时间戳。 ```python data = {'time_stamp': ['2020-01-01', '2020-01-05', '2020-01-10', '2020-01-15'], 'event': ['Event 1', 'Event 2', 'Event 3', 'Event 4']} df = pd.DataFrame(data) df['time_stamp'] = pd.to_datetime(df['time_stamp']) ``` 4. 准备画布,并设置绘图参数 ```python fig, ax = plt.subplots(figsize=(10,5)) ``` 5. 在画布上绘制时间轴 ```python ax.plot(df['time_stamp'], [0]*len(df), '|', markersize=20, color='g') ``` 6. 在时间轴上添加事件标签 ```python for i, txt in enumerate(df['event']): ax.annotate(txt, (df['time_stamp'][i], 0), xytext=(5,-15), textcoords='offset points', rotation=90) ``` 7. 隐藏坐标轴和边框 ```python ax.axis('off') ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) ax.spines['left'].set_visible(False) ax.spines['bottom'].set_visible(False) ``` 8. 显示绘图 ```python plt.show() ``` 这样,就可以得到一个简单的时间轴。可以根据需要进行调整和美化,添加更多细节和交互功能,实现更加复杂的效果。 ### 回答3: Python实现timeline时间轴的方法可以有很多种,以下是一种可能的实现: 1. 数据处理 首先,我们需要将timeline中的所有事件按照时间顺序排列,这就涉及到数据处理的问题。一种简单的方法是将每个事件存储为一个字典,其中包含该事件的时间、标题、描述等信息,并将所有事件存储在一个列表中。然后,我们可以使用Python内置的sorted()函数将这个列表按照事件时间排序。 2. 可视化 接下来,我们需要将排好序的事件数据可视化成时间轴。Python中有很多可用的可视化库,比如Matplotlib、PyQtGraph等。这里我们选用Matplotlib。 在Matplotlib中,我们可以使用plot()函数绘制时间轴的基本轮廓,然后使用annotate()函数添加事件的标题和描述等信息。具体绘制代码如下: ```python import matplotlib.pyplot as plt # 绘制时间轴基本轮廓 plt.plot([0, 100], [0, 0], 'k-', linewidth=2) plt.plot([50, 50], [-0.5, 0.5], 'k-', linewidth=2) # 遍历事件数据,逐个添加事件的标题和描述 for event in events: time = event['time'] title = event['title'] desc = event['desc'] plt.annotate(title, xy=(time, 0.2), ha='center', va='bottom', fontsize=8) plt.annotate(desc, xy=(time, -0.2), ha='center', va='top', fontsize=8) # 显示时间轴 plt.axis('off') plt.show() ``` 3. 交互和动画 如果要让时间轴更加交互和生动,我们可以使用Matplotlib的事件处理功能和动画功能。比如,我们可以添加鼠标悬停事件处理函数,使得鼠标悬停在事件上时,显示该事件的详细信息。代码如下: ```python def on_mouse_move(event): if not event.inaxes: return for ann in ax.texts: if ann.contains(event)[0]: ann.set_visible(True) else: ann.set_visible(False) fig, ax = plt.subplots() for event in events: time = event['time'] title = event['title'] desc = event['desc'] ann = ax.annotate(title, xy=(time, 0.2), ha='center', va='bottom', fontsize=8) ax.annotate(desc, xy=(time, -0.2), ha='center', va='top', fontsize=8) ann.set_visible(False) fig.canvas.mpl_connect('motion_notify_event', on_mouse_move) ``` 另外,我们还可以使用动画功能,将时间轴中的事件逐个显示出来。这需要用到Matplotlib的animation模块。具体实现步骤可以参考Matplotlib官方文档和示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值