实现TimeLine时间轴 recyclerview

先看效果

在这里插入图片描述

导入依赖

 implementation 'androidx.recyclerview:recyclerview:1.2.1'

acrivity_timeline.xml

<androidx.recyclerview.widget.RecyclerView
        android:id="@+id/my_rv"
        android:layout_width="409dp"
        android:layout_height="729dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

list_cell.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="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="10sp"
        android:text="New Text"
        android:id="@+id/item_title" />

    <TextView
        android:id="@+id/item_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/item_title"
        android:text="New Text"
        android:textSize="10sp" />
</RelativeLayout>

TimelineActivity.java

public class TimelineActivity extends AppCompatActivity  {
    private RecyclerView rv;
    private ArrayList<HashMap<String,Object>> listItem;
    private DiyAdapter myAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_timeline);

        // 初始化显示的数据
        initData();

        // 绑定数据到RecyclerView
        initView();
     
    }

    /**
     * 初始化显示的数据
     */
    public void initData(){
        /*在数组中存放数据*/
        listItem = new ArrayList<HashMap<String, Object>>();

        HashMap<String, Object> map1 = new HashMap<String, Object>(20);
        HashMap<String, Object> map2 = new HashMap<String, Object>(20);
        HashMap<String, Object> map3 = new HashMap<String, Object>(20);
        HashMap<String, Object> map4 = new HashMap<String, Object>(20);
        HashMap<String, Object> map5 = new HashMap<String, Object>(20);
        HashMap<String, Object> map6 = new HashMap<String, Object>(20);

        map1.put("item_title", "美国谷歌公司已发出");
        map1.put("item_text", "发件人:谷歌 CEO");
        listItem.add(map1);

        map2.put("item_title", "国际顺丰已收入");
        map2.put("item_text", "等待中转");
        listItem.add(map2);

        map3.put("item_title", "国际顺丰转件中");
        map3.put("item_text", "下一站中国");
        listItem.add(map3);

        map4.put("item_title", "中国顺丰已收入");
        map4.put("item_text", "下一站深圳龙岗区代理");
        listItem.add(map4);

        map5.put("item_title", "您的包裹由骑手派件中");
        map5.put("item_text", "等待派件");
        listItem.add(map5);

        map6.put("item_title", "深圳公司已签收");
        map6.put("item_text", "收件人:你的名字");
        listItem.add(map6);
    }

    /**
     *  绑定数据到RecyclerView
     */
    public void initView(){
        rv = (RecyclerView) findViewById(R.id.my_rv);
        //使用线性布局
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        rv.setLayoutManager(layoutManager);
        rv.setHasFixedSize(true);

        //用自定义分割线类设置分割线
        rv.addItemDecoration(new DividerItemDecoration(this));

        //为ListView绑定适配器
        myAdapter = new DiyAdapter(this,listItem);
        rv.setAdapter(myAdapter);
    }

}

car图片所在文件夹

在这里插入图片描述

DividerItemDecoration.java

public class DividerItemDecoration extends RecyclerView.ItemDecoration {

    // 写右边字的画笔(具体信息)
    private final Paint mPaint;

    // 写左边日期字的画笔( 时间 + 日期)
    private final Paint mPaint1;
    private final Paint mPaint2;

    // 左 上偏移长度
    private final int leftInterval;
    private final int topInterval;

    // 轴点半径
    private final int circleRadius;

    // 图标
    private final Bitmap mIcon;


    /**
     *  在构造函数里进行绘制的初始化,如画笔属性设置等
     */
    public DividerItemDecoration(Context context) {

        // 轴点画笔(红色)
        mPaint = new Paint();
        mPaint.setColor(Color.RED);

        // 左边时间文本画笔(蓝色)
        // 此处设置了两只分别设置 时分 & 年月
        mPaint1 = new Paint();
        mPaint1.setColor(Color.BLUE);
        mPaint1.setTextSize(50);

        mPaint2 = new Paint();
        mPaint2.setColor(Color.GREEN);
        mPaint2.setTextSize(30);

        // 赋值ItemView的左偏移长度为300
        leftInterval = 300;

        // 赋值ItemView的上偏移长度为80
        topInterval = 80;

        // 赋值轴点圆的半径为5
        circleRadius = 5;


        // 获取图标资源
        mIcon = BitmapFactory.decodeResource(context.getResources(), R.mipmap.car);

    }

    /**
     * 重写getItemOffsets()方法
     * 作用:设置ItemView 左 & 上偏移长度
     * @param outRect
     * @param view
     * @param parent
     * @param state
     */
    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);

        // 设置ItemView的左 & 上偏移长度分别为300 px & 80px,即此为onDraw()可绘制的区域
        outRect.set(leftInterval, topInterval, 0, 0);

    }


    /**
     *  重写onDraw()
     *  作用:在间隔区域里绘制时光轴线 & 时间文本
     * @param c
     * @param parent
     * @param state
     */
    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);

        // 获取RecyclerView的Child view(即可见的item view)的个数
        int childCount = parent.getChildCount();

        // 遍历每个Item,分别获取它们的位置信息,然后再绘制对应的分割线
        for (int i = 0; i < childCount; i++) {

            // 获取每个Item对象
            View child = parent.getChildAt(i);

            /**
             * 绘制轴点
             */
            // 轴点 = 圆 = 圆心(x,y)
            float centerX = child.getLeft() - leftInterval / 3;
            float centerY = child.getTop() - topInterval + (topInterval + child.getHeight()) / 2;
            // 绘制轴点圆
            //c.drawCircle(centerX, centerY, circleRadius, mPaint);
            // 通过Canvas绘制角标
            c.drawBitmap(mIcon,centerX - circleRadius ,centerY - circleRadius,mPaint);

            /**
             * 绘制上半轴线
             */
            // 上端点坐标(x,y)
            float upLineUpY = child.getTop() - topInterval;

            // 下端点坐标(x,y)
            float upLineBottomY = centerY - circleRadius;

            //绘制上半部轴线
            c.drawLine(centerX, upLineUpY, centerX, upLineBottomY, mPaint);

            /**
             * 绘制下半轴线
             */
            // 上端点坐标(x,y)
            float downLineUpY = centerY + circleRadius + 40;

            // 下端点坐标(x,y)
            float downLineBottomY = child.getBottom();

            //绘制下半部轴线
            c.drawLine(centerX, downLineUpY, centerX, downLineBottomY, mPaint);


            /**
             * 绘制左边时间文本
             */
            // 获取每个Item的位置
            int index = parent.getChildAdapterPosition(child);
            // 设置文本起始坐标
                    float textX = child.getLeft() - leftInterval * 5 / 6;

                    // 根据Item位置设置时间文本
                    switch (index) {
                        case (0):
                            // 设置日期绘制位置
                            c.drawText("13:40", textX, upLineBottomY, mPaint1);
                            c.drawText("2022.8.11", textX - 5, upLineBottomY + 40, mPaint2);
                            break;
                        case (1):
                            // 设置日期绘制位置
                            c.drawText("17:33", textX, upLineBottomY, mPaint1);
                            c.drawText("2022.8.11", textX - 5, upLineBottomY + 40, mPaint2);
                            break;
                        case (2):
                            // 设置日期绘制位置
                            c.drawText("20:13", textX, upLineBottomY, mPaint1);
                            c.drawText("2022.8.11", textX - 5, upLineBottomY + 40, mPaint2);
                    break;
                case (3):
                    // 设置日期绘制位置
                    c.drawText("10:40", textX, upLineBottomY, mPaint1);
                    c.drawText("2022.8.12", textX - 5, upLineBottomY + 40, mPaint2);
                    break;
                case (4):
                    // 设置日期绘制位置
                    c.drawText("11:20", textX, upLineBottomY, mPaint1);
                    c.drawText("2022.8.12", textX - 5, upLineBottomY + 40, mPaint2);
                    break;
                case (5):
                    // 设置日期绘制位置
                    c.drawText("11:40", textX, upLineBottomY, mPaint1);
                    c.drawText("2022.8.12", textX - 5, upLineBottomY + 40, mPaint2);
                    break;
                default:c.drawText("已签收", textX, upLineBottomY, mPaint1);
            }
        }
    }

}


DiyAdapter .java

public class DiyAdapter extends RecyclerView.Adapter {
    private ArrayList<HashMap<String,Object>> listItem;
    private LayoutInflater inflater;

    public DiyAdapter(Context context, ArrayList<HashMap<String,Object>> listItem) {
        inflater = LayoutInflater.from(context);
        this.listItem = listItem;
    }

    class DiyViewHolder extends RecyclerView.ViewHolder{
        private TextView title,text;

        public DiyViewHolder(View root){
            super(root);
            title = (TextView) root.findViewById(R.id.item_title);
            text = (TextView) root.findViewById(R.id.item_text);
        }

        public TextView getTitle(){
           return title;
        }
        public TextView getText(){
            return text;
        }
    }

    /**
     * 把View绑定Item布局
     * @param parent
     * @param viewType
     * @return
     */
    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new DiyViewHolder(inflater.inflate(R.layout.list_cell,null));
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        DiyViewHolder dvh = (DiyViewHolder) holder;
        //绑定数据到ViewHolder
        dvh.title.setText((String)listItem.get(position).get("item_title"));
        dvh.text.setText((String)listItem.get(position).get("item_text"));
    }

    /**
     * 返回Item数目
     * @return
     */
    @Override
    public int getItemCount() {
        return listItem.size();
    }
}

注:
学习自https://carsonho.blog.csdn.net/article/details/75005994

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答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官方文档和示例。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值