实现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

猜你喜欢

转载自blog.csdn.net/qq_44256828/article/details/126304758