自学内容网 自学内容网

仿iOS日历、飞书日历、Google日历的日模式

仿iOS日历、飞书日历、Google日历的日模式,24H内事件可自由上下拖动、自由拉伸。

以下是效果图:

具体实现比较简单,代码如下:



import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ScrollView;

import androidx.annotation.Nullable;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

//4、Java to c#
public class MultiRectView extends View {
    private Paint paintRect;
    private Paint borderPaint ;
    private Paint paintLine;
    private Paint paintDragText;
    private List<RectF> rectangles;
    private List<Map> rectanglesMapList;
    private RectF currentRect; // 当前操作的矩形
    private RectF preRect; // 操作的前一个矩形
    private int currentRectIndex = 0;// 当前被选中的矩形
    private float rectWidth = 200f; // 矩形宽度
    private float rectHeight = 100f; // 矩形高度
    private int currentHandle; // 记录当前操作的控制点
    private float lastX, lastY; // 手指最后位置
    private float preX, preY; // 手指起始位置
    private TextPaint textPaint;
    private Paint shadowPaint; // 用于阴影效果

    // 控制点
    private static final int NONE = -1;
    private static final int LEFT_TOP = 0;
    private static final int RIGHT_TOP = 1;
    private static final int LEFT_BOTTOM = 2;
    private static final int RIGHT_BOTTOM = 3;
    private static final int MOVE_RECT = 4;

    // 刻度设置
    private final int SCALE_INTERVAL = 30; // 30分钟
    private final int TOTAL_SCALES = 24 * 4; // 24小时,每小时4个15分钟刻度
    // 设置最小高度
    private final int MIN_RECT_HEIGHT = 100;
    long lineWidth = 6;
    long lineLen = 30;
    private String[] hours;
    private GestureDetector gestureDetector;
    private Context mContext;
    private onclickListener onclickListener;
    private onLongclicklistener onLongclickListener;
    private long longPressStartTime = 0;//长按时间
    private boolean isDragging = false;
    private ScrollView scrollView;
    private int mScaleWidth = 30;//上下间距
    private int mScaleLineX = 140;//横线距离左侧的起始距离点
    private int mScaleLineText = 30;//刻度的起始点
    private int mScaleRectToLeft = 150;//矩形距离左侧间距
    private List<String> texts; // 存储每个矩形内的文本
    private Canvas mCanvas;
    private String topText = "";
    private String bottomText = "";
    int topScale = 0;
    int bottomScale = 0;
    private RectF rectMove;
    private boolean isCancleClickStatus = true;
    private boolean isLongPressStatus = false;//长按状态
    //计时器,计时点击时长
    Timer timer;
    TimerTask timerTask;
    private final int LONGPRESSTIME = 500;//长按超过0.5秒,触发长按事件
    private float cornerRadius = 15f; // 圆角半径
    private List<ActiviesDataModel> activiesDataModelListl;
    private float offsetAmount = 20; // 偏移量,具体根据需求调整

    public MultiRectView(Context context) {
        super(context);
        mContext = context;
        init();
    }

    public MultiRectView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        init();
    }

    public MultiRectView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        init();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int reHeight = resolveSize(heightSize, heightMeasureSpec);
        setMeasuredDimension(widthMeasureSpec, reHeight);
    }

    public void setScrollView(ScrollView scrollView1) {
        this.scrollView = scrollView1;
    }

    private void init() {
        texts = new ArrayList<>();
        rectangles = new ArrayList<>();
        rectanglesMapList = new ArrayList<>();

        // 初始化填充画笔
        paintRect = new Paint();
        paintRect.setAntiAlias(true);
        paintRect.setStyle(Paint.Style.FILL);
        paintRect.setColor(getResources().getColor(R.color.purple_200));
        paintRect.setStrokeCap(Paint.Cap.ROUND);
        paintRect.setStrokeWidth(3);//控制矩形宽高

        // 初始化边框画笔
        borderPaint = new Paint();
        borderPaint.setAntiAlias(true);
        borderPaint.setStyle(Paint.Style.STROKE);
        borderPaint.setColor(getResources().getColor(R.color.purple_300)); // 设置边框颜色为黄色
        borderPaint.setStrokeWidth(3); // 设置边框宽度

        //划线属性
        paintLine = new Paint();
        paintLine.setColor(Color.RED);

        //动态显示时间标签的画笔属性
        paintDragText = new Paint();
        paintDragText.setColor(Color.GREEN);
        paintDragText.setTextSize(30);

        //左侧时间的画笔属性
        textPaint = new TextPaint();
        textPaint.setColor(Color.BLACK);
        textPaint.setTextSize(32); // 设置文本大小

        //阴影
        shadowPaint = new Paint();
        shadowPaint.setAntiAlias(true);
        shadowPaint.setStyle(Paint.Style.FILL); // 设为填充样式
        shadowPaint.setColor(getResources().getColor(R.color.purple_300)); // 阴影主体的颜色
        shadowPaint.setShadowLayer(10f, 0f, 0f, getResources().getColor(R.color.black2)); // 设置阴影外圈渐变效果

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawScale(canvas); // 绘制刻度线、时间刻度

        for (int i = 0; i < rectangles.size(); i++) {
            if(i != currentRectIndex){// 绘制未选中的矩形
                RectF rect = rectangles.get(i);
                // 检查重叠并调整位置
//                if (isOverlapping(rect, i)) {
//                    rect.left -= offsetAmount; // 向左偏移
//                }
                drawRectAndText(canvas, rect, i);//画矩形框、内部写字
                drawCurrentScale(canvas, rect, i);//绘制显示实时刻度
            }
        }
        // 绘制当前选中的矩形,确保其在最上层
        if (currentRectIndex != -1) {
            RectF selectedRect = rectangles.get(currentRectIndex);
            drawRectAndText(canvas, selectedRect, currentRectIndex,true); // 画选中的矩形框、内部写字
            drawCurrentScale(canvas, selectedRect,currentRectIndex); // 绘制选中的矩形显示实时刻度
        }
        this.mCanvas = canvas;
    }

    private boolean isOverlapping(RectF currentRect, int currentIndex) {
        for (int i = 0; i < rectangles.size(); i++) {
            if (i != currentIndex) {
                RectF otherRect = rectangles.get(i);
                if (RectF.intersects(currentRect, otherRect)) {
                    return true; // 矩形重叠
                }
            }
        }
        return false; // 矩形不重叠
    }


    private void drawScale(Canvas canvas) {
        // 绘制15分钟刻度线
        for (int n = 0; n <= TOTAL_SCALES; n++) {
            float y = n * mScaleWidth; // 计算刻度Y坐标

            // 计算并绘制时间标签(15分钟为单位)
            if (n % 4 == 0) { // 但每小时显示并绘制一次
                int hour = n / 4;
                if ((n / 4 + "").contains("24")) {
                    hour = 0;
                }
                if (y == 0) {//第一根线防止画不全
                    y = 15;
                }
                String timeText = String.format("%02d:00", hour);
                canvas.drawText(timeText, mScaleLineX - 100, y + 10, textPaint); // 绘制时间文本
                canvas.drawLine(mScaleLineX, y, getWidth() - 30, y + 20, paintLine); // 绘制刻度线
            }

        }

    }

    private String finalStartTime = "";
    private String finalEndTime = "";

    private void drawCurrentScale(Canvas canvas, RectF rect, int index) {//绘制显示实时的刻度
        // 计算矩形边界的时间刻度值
        topScale = (int) Math.round(rect.top / (mScaleWidth)); // 计算矩形上边界的刻度
        bottomScale = Math.round(rect.bottom / (mScaleWidth)); // 计算矩形下边界的刻度

        if (currentRect != rect) {//只有当前点击的矩形参与显示
            return;
        }
        boolean isLongPressStatus = (activiesDataModelListl.get(index)).isLongPressStatus();
        if (isLongPressStatus) {
            finalStartTime = "";
            finalEndTime = "";
            // 确保边界值在可用范围内
            if (topScale >= 0 && topScale < TOTAL_SCALES) {
                rectMove = rect;
                topText = String.format("%02d:%02d", topScale / 4, (topScale % 4) * 15);
                finalStartTime = topText;
                //  canvas.drawText(topText, mScaleLineX + 10, rect.top + 20, textPaint); // 绘制上边界刻度
                canvas.drawText(topText, mScaleLineX - 100, rect.top + 20, paintDragText); // 绘制上边界刻度
            }

            if (bottomScale >= 0 && bottomScale < TOTAL_SCALES) {
                bottomText = String.format(" %02d:%02d", bottomScale / 4, (bottomScale % 4) * 15);
                finalEndTime = bottomText;
                canvas.drawText(bottomText, mScaleLineX - 100, rect.bottom - 10, paintDragText); // 绘制下边界刻度
                //canvas.drawText(bottomText, mScaleLineX + 10, rect.bottom - 10, textPaint); // 绘制下边界刻度
            }

            if (!TextUtils.isEmpty(finalStartTime) && !TextUtils.isEmpty(finalEndTime)) {//更新调整后的时间
                activiesDataModelListl.get(index).setStart_time(finalStartTime);
                activiesDataModelListl.get(index).setEnd_time(finalEndTime);
            }
        } else {

        }

    }

    private void drawRectAndText(Canvas canvas, RectF rect, int index) {

        canvas.drawRoundRect(rect, cornerRadius, cornerRadius, paintRect); // 绘制圆角矩形-填充
        canvas.drawRoundRect(rect, cornerRadius, cornerRadius, borderPaint); // 绘制圆角矩形-边框
        boolean isLongPressStatus = (activiesDataModelListl.get(index)).isLongPressStatus();
        //绘制矩形的四个边角
        if (isLongPressStatus) {
            if (currentRect != null && currentRect == rect) {
                // lt h 左上角
                //  canvas.drawLine(rect.left, rect.top, rect.left + lineLen, rect.top, paintRect);
                // lt v
                //    canvas.drawLine(rect.left, rect.top, rect.left, rect.top + lineLen, paintRect);

                // rt h 右上角
                //  canvas.drawLine(rect.right - lineLen, rect.top, rect.right, rect.top, paintRect);
                // rt v
                //   canvas.drawLine(rect.right, rect.top, rect.right, rect.top + lineLen, paintRect);

                // lb h左下角
                //   canvas.drawLine(rect.left, rect.bottom, rect.left + lineLen, rect.bottom, paintRect);
                // lb v
                //       canvas.drawLine(rect.left, rect.bottom - lineLen, rect.left, rect.bottom, paintRect);

                // rb h 右下角
                //   canvas.drawLine(rect.right - lineLen, rect.bottom, rect.right, rect.bottom, paintRect);
                // rb v
                //  canvas.drawLine(rect.right, rect.bottom - lineLen, rect.right, rect.bottom, paintRect);

                drawShadowEffect(canvas, rect); // 绘制阴影效果
            }

        }

        ActiviesDataModel activiesDataModel = activiesDataModelListl.get(index);
        String name = activiesDataModel.getPop_name();
        String address = activiesDataModel.getPop_address();
        int popdb_id = activiesDataModel.getPopdb_id();
        String startTime = activiesDataModel.getStart_time();
        String endTime = activiesDataModel.getEnd_time();
        String value = name + " \n " + address + " \n " + startTime + " -- " + endTime;
        // 绘制矩形内的文本
        StaticLayout staticLayout = new StaticLayout(value, textPaint,
                (int) rect.width(), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
        canvas.save();
        canvas.translate(rect.left, rect.top); // 移动画布到矩形的左上角
        staticLayout.draw(canvas);
        canvas.restore();

    }

    private void drawRectAndText(Canvas canvas, RectF rect, int index,boolean isInUp) {

        canvas.drawRoundRect(rect, cornerRadius, cornerRadius, paintRect); // 绘制圆角矩形-填充
        canvas.drawRoundRect(rect, cornerRadius, cornerRadius, borderPaint); // 绘制圆角矩形-边框
        boolean isLongPressStatus = (activiesDataModelListl.get(index)).isLongPressStatus();
        //绘制矩形的四个边角
        if (isLongPressStatus) {
            if (currentRect != null && currentRect == rect) {
                // lt h 左上角
                //  canvas.drawLine(rect.left, rect.top, rect.left + lineLen, rect.top, paintRect);
                // lt v
                //    canvas.drawLine(rect.left, rect.top, rect.left, rect.top + lineLen, paintRect);

                // rt h 右上角
                //  canvas.drawLine(rect.right - lineLen, rect.top, rect.right, rect.top, paintRect);
                // rt v
                //   canvas.drawLine(rect.right, rect.top, rect.right, rect.top + lineLen, paintRect);

                // lb h左下角
                //   canvas.drawLine(rect.left, rect.bottom, rect.left + lineLen, rect.bottom, paintRect);
                // lb v
                //       canvas.drawLine(rect.left, rect.bottom - lineLen, rect.left, rect.bottom, paintRect);

                // rb h 右下角
                //   canvas.drawLine(rect.right - lineLen, rect.bottom, rect.right, rect.bottom, paintRect);
                // rb v
                //  canvas.drawLine(rect.right, rect.bottom - lineLen, rect.right, rect.bottom, paintRect);

                drawShadowEffect(canvas, rect); // 绘制阴影效果
            }

        }

        ActiviesDataModel activiesDataModel = activiesDataModelListl.get(index);
        String name = activiesDataModel.getPop_name();
        String address = activiesDataModel.getPop_address();
        int popdb_id = activiesDataModel.getPopdb_id();
        String startTime = activiesDataModel.getStart_time();
        String endTime = activiesDataModel.getEnd_time();
        String value = name + " \n " + address + " \n " + startTime + " -- " + endTime;
        // 绘制矩形内的文本
        StaticLayout staticLayout = new StaticLayout(value, textPaint,
                (int) rect.width(), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
        canvas.save();
        canvas.translate(rect.left, rect.top); // 移动画布到矩形的左上角
        staticLayout.draw(canvas);
        canvas.restore();

    }


    private void drawShadowEffect(Canvas canvas, RectF rect) {
        // 绘制阴影
        canvas.drawRoundRect(rect, cornerRadius, cornerRadius, shadowPaint); // 绘制圆角矩形
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float currentX = event.getX();
        float currentY = event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // 检查是否按下了控制点
                longPressStartTime = 0;
                for (int i = 0; i < rectangles.size(); i++) {
                    RectF rect = rectangles.get(i);

                    if (isInHandle(currentX, currentY, rect, LEFT_TOP)) {
                        currentRect = rect;
                        currentHandle = LEFT_TOP;
                    } else if (isInHandle(currentX, currentY, rect, RIGHT_TOP)) {
                        currentRect = rect;
                        currentHandle = RIGHT_TOP;
                    } else if (isInHandle(currentX, currentY, rect, LEFT_BOTTOM)) {
                        currentRect = rect;
                        currentHandle = LEFT_BOTTOM;
                    } else if (isInHandle(currentX, currentY, rect, RIGHT_BOTTOM)) {
                        currentRect = rect;
                        currentHandle = RIGHT_BOTTOM;
                    } else if (rect.contains(currentX, currentY)) {
                        // 检测是否按下矩形
                        currentRectIndex = i;
                        longPressStartTime = System.currentTimeMillis(); // 记录长按开始时间
                        currentRect = rect;
                        currentHandle = MOVE_RECT;

                        if (preRect != currentRect) {//前后两个矩形不是同一个
                            //  isLongPressStatus = false;
                        }

                        timer = new Timer();
                        timerTask = new TimerTask() {
                            @Override
                            public void run() {
                                //长按逻辑触发

                                if(currentRectIndex!=-1){
                                    activiesDataModelListl.get(currentRectIndex).setLongPressStatus(true);
                                    // 长按触摸区域,禁止父容器 (ScrollView) 拦截触摸事件
                                    if (scrollView != null) {
                                        scrollView.requestDisallowInterceptTouchEvent(true);
                                    }
                                }

                                invalidate(); // 刷新视图
                            }
                        };
                        timer.schedule(timerTask, LONGPRESSTIME, 1000 * 60 * 60 * 24);

                    } else {
                        // activiesDataModelListl.get(i).setLongPressStatus(false);
                    }
                }
                lastX = currentX;
                lastY = currentY;
                preX = currentX;
                preY = currentY;
                isCancleClickStatus = true;
                try {
                    boolean longPressStatus = activiesDataModelListl.get(currentRectIndex).isLongPressStatus();
                    if (currentRect != null && longPressStatus) {
                        // 触摸区域在矩形内,禁止父容器 (ScrollView) 拦截触摸事件
                        if (scrollView != null) {
                            scrollView.requestDisallowInterceptTouchEvent(true);
                        }

                    }
                } catch (Exception e) {
                    e.getMessage();
                }

                break;

            case MotionEvent.ACTION_MOVE:
                if (currentRect != null) {
                    float dx = currentX - lastX;
                    float dy = currentY - lastY;
                    boolean isLongPressStatus = false;
                    if(currentRectIndex!=-1){
                        isLongPressStatus = (activiesDataModelListl.get(currentRectIndex)).isLongPressStatus();
                    }
                    switch (currentHandle) {
                        case LEFT_TOP:
                            //  currentRect.left += dx;//只允许上下拉伸 禁止左右拉伸
                            if (isLongPressStatus) {
                                currentRect.top += dy;
                            }

                            break;
                        case RIGHT_TOP:
                            //   currentRect.right += dx;
                            if (isLongPressStatus) {
                                currentRect.top += dy;
                            }

                            break;
                        case LEFT_BOTTOM:
                            //  currentRect.left += dx;
                            if (isLongPressStatus) {
                                currentRect.bottom += dy;
                            }

                            break;
                        case RIGHT_BOTTOM:
                            //    currentRect.right += dx;
                            if (isLongPressStatus) {
                                currentRect.bottom += dy;
                            }

                            break;
                        case MOVE_RECT:
                            if (currentRectIndex != -1) {
                                long pressDuration = System.currentTimeMillis() - longPressStartTime;
                                if (isLongPressStatus) {//长按的时间长度
                                    //     isDragging = true; // 开始拖动
                                    // 计算拖动距离
                                    RectF rect = rectangles.get(currentRectIndex);
                                    rect.offset(0, (int) dy);//dx=0 只允许Y轴滑动 不允许x轴左右滑动

                                }
                            }
                            break;
                    }

                    for (int n = 0; n < rectangles.size(); n++) {
                        RectF rect = rectangles.get(n);
                        boolean isLongPressStatusTemp = (activiesDataModelListl.get(n)).isLongPressStatus();
                        if (rect != currentRect) {
                            activiesDataModelListl.get(n).setLongPressStatus(false);
                        }
                    }

                    //取消计时
                    timerTask.cancel();
                    timer.cancel();

                    // 更新最后位置
                    lastX = currentX;
                    lastY = currentY;
                    invalidate(); // 刷新视图

                }
                break;

            case MotionEvent.ACTION_UP:
                if (currentRect != null) {
                    float dx = currentX - preX;
                    float dy = currentY - preY;
                    boolean isLongPressStatus = false;
                    if(currentRectIndex!=-1){
                        isLongPressStatus = (activiesDataModelListl.get(currentRectIndex)).isLongPressStatus();
                    }

                    if (dx == 0 && dy == 00) {//此处应该用绝对值来判断一个较小的数值
                        if (!isLongPressStatus) {//不是长按状态的矩形
                            boolean isHasTrue = false;
                            for (int n = 0; n < rectangles.size(); n++) {
                                RectF rect = rectangles.get(n);
                                boolean isLongPressStatusTemp = (activiesDataModelListl.get(n)).isLongPressStatus();
                                if (isLongPressStatusTemp) {
                                    isHasTrue = true;//检查是否存在点击状态的矩形
                                }

                                if (rect != currentRect) {
                                    activiesDataModelListl.get(n).setLongPressStatus(false);
                                }
                            }

                            invalidate(); // 刷新视图

                            if (isHasTrue) {

                            } else {//如果没有选中状态矩形 则允许回调点击事件
                                if (onclickListener != null) {
                                    onclickListener.onclick(currentRectIndex + "--" + activiesDataModelListl.get(currentRectIndex).getPop_name());
                                }
                            }

                        } else {//点击的是长按状态的矩形

                        }
                    }

                    preRect = currentRect;
                } else {//点击在非矩形区域
                    isCancleClickStatus = false;
                    //   isLongPressStatus = false;
                    try {
                        (activiesDataModelListl.get(currentRectIndex)).setLongPressStatus(false);
                    } catch (Exception e) {
                        e.getMessage();
                    }

                    invalidate(); // 刷新视图
                }
                // currentRectIndex = -1; // 取消触摸
                currentRect = null;
                currentHandle = NONE;
                //取消计时
                timerTask.cancel();
                timer.cancel();

                try {
                    boolean longPressStatusUp = activiesDataModelListl.get(currentRectIndex).isLongPressStatus();

                    // 恢复父容器 (ScrollView) 拦截触摸事件
                    if (scrollView != null && !longPressStatusUp) {
                        scrollView.requestDisallowInterceptTouchEvent(false);
                    }
                } catch (Exception e) {
                    e.getMessage();
                }

                break;
            case MotionEvent.ACTION_CANCEL:
                currentHandle = NONE;
                currentRectIndex = -1; // 取消触摸
                isLongPressStatus = false;
                //  (activiesDataModelListl.get(currentRectIndex)).setLongPressStatus(false);
                // 恢复父容器 (ScrollView) 拦截触摸事件
                if (scrollView != null) {
                    scrollView.requestDisallowInterceptTouchEvent(false);
                }
                break;
        }
        return true;
    }

    private boolean isInHandle(float x, float y, RectF rect, int handle) {
        float handleSize = 60f; // 控制点的尺寸
        switch (handle) {
            case LEFT_TOP:
                return x >= rect.left - handleSize / 2 && x <= rect.left + handleSize / 2 &&
                        y >= rect.top - handleSize / 2 && y <= rect.top + handleSize / 2;
            case RIGHT_TOP:
                return x >= rect.right - handleSize / 2 && x <= rect.right + handleSize / 2 &&
                        y >= rect.top - handleSize / 2 && y <= rect.top + handleSize / 2;
            case LEFT_BOTTOM:
                return x >= rect.left - handleSize / 2 && x <= rect.left + handleSize / 2 &&
                        y >= rect.bottom - handleSize / 2 && y <= rect.bottom + handleSize / 2;
            case RIGHT_BOTTOM:
                return x >= rect.right - handleSize / 2 && x <= rect.right + handleSize / 2 &&
                        y >= rect.bottom - handleSize / 2 && y <= rect.bottom + handleSize / 2;
            default:
                return false;
        }
    }

    public void addRectangle(float left, float top, int tags, String textC) {
        //rectWidth = getWidth()-400;
        RectF rect = new RectF(left, top, 1010, top + rectHeight);
        Map<Integer, RectF> map = new HashMap<Integer, RectF>();
        map.put(tags, rect);
        texts.add(textC);
        rectanglesMapList.add(map);
        rectangles.add(rect);
        invalidate(); // 刷新视图
    }


    public void addRectangle(ArrayList<ActiviesDataModel> list) {
        this.activiesDataModelListl = list;
        for (int i = 0; i < activiesDataModelListl.size(); i++) {
            ActiviesDataModel activiesDataModel = activiesDataModelListl.get(i);
            String name = activiesDataModel.getPop_name();
            String address = activiesDataModel.getPop_address();
            int popdb_id = activiesDataModel.getPopdb_id();
            String startTime = activiesDataModel.getStart_time();
            String endTime = activiesDataModel.getEnd_time();


            // 需要根据具体的业务逻辑计算 left 和 top
            float top_start = formatTimeToYValues(startTime);
            float bootom_end = formatTimeToYValues(endTime);
            float rect_height = bootom_end - top_start;
            float rect_width = this.getWidth() - mScaleRectToLeft;
            RectF rect = new RectF(mScaleRectToLeft, top_start, 1010, top_start + rect_height);
            Map<Integer, RectF> map = new HashMap<>();
            map.put(i, rect);
            texts.add(name + " \n " + address + " \n " + startTime + " \n " + endTime);
            rectanglesMapList.add(map);
            rectangles.add(rect);
        }

        invalidate(); // 刷新视图
    }


    // 转换刻度值为时间字符串
    private float formatTimeToYValues(String time_value) {
        float y_value = 0;
        String closesTime = findClosestTimeRange(time_value);
        // 绘制15分钟刻度线
        for (int n = 0; n <= TOTAL_SCALES; n++) {
            float y = n * mScaleWidth; // 计算刻度Y坐标

            int hour = n / 4;
            int minute = (n % 4) * 15; // 每个刻度15分钟
            if ((n / 4 + "").contains("24")) {
                hour = 0;
            }
            String timeHMText = String.format("%02d:%02d", hour, minute);
            if (closesTime.equals(timeHMText)) {
                y_value = y;
                break;
            }

        }

        return y_value;
    }

    public String findClosestTimeRange(String time) {
        String[] parts = time.split(":");
        int hour = Integer.parseInt(parts[0]);
        int minute = Integer.parseInt(parts[1]);

        int totalMinutes = hour * 60 + minute;

        // 找到最接近的15分钟的倍数
        int closestMultiple = Math.round((float) totalMinutes / 15) * 15;

        // 将最接近的总分钟数转换回HH:MM格式
        int closestHour = closestMultiple / 60;
        int closestMinute = closestMultiple % 60;

        return String.format("%02d:%02d", closestHour, closestMinute);
    }

    public void setonclicklistener(onclickListener listener) {
        this.onclickListener = listener;
    }

    public void setonLongclicklistener(onLongclicklistener listener) {
        this.onLongclickListener = listener;
    }

    public interface onclickListener {

        void onclick(String value);
    }

    public interface onLongclicklistener {
        void onLongclick(String value);
    }

}

外面传入数据调用即可:

MultiRectView multiRectView = findViewById(R.id.multiRectView);
        multiRectView.setonclicklistener(this);
        multiRectView.setonLongclicklistener(this);
        multiRectView.setScrollView(scrollView);


        ActiviesDataModel activiesDataModel1 = new ActiviesDataModel();
        activiesDataModel1.setPop_name(" POP Name1 万客隆精选超市");
        activiesDataModel1.setPop_address("南京东路1024弄");
        activiesDataModel1.setPopdb_id(215639);
        activiesDataModel1.setStart_time("06:40");
        activiesDataModel1.setEnd_time("08:30");

        ActiviesDataModel activiesDataModel2 = new ActiviesDataModel();
        activiesDataModel2.setPop_name(" POP Name2 京东自营超市");
        activiesDataModel2.setPop_address("南京东路1024弄");
        activiesDataModel2.setPopdb_id(215638);
        activiesDataModel2.setStart_time("09:10");
        activiesDataModel2.setEnd_time("11:50");

        ActiviesDataModel activiesDataModel3 = new ActiviesDataModel();
        activiesDataModel3.setPop_name(" POP Name3 拼多多百亿补贴超市");
        activiesDataModel3.setPop_address("南京东路1024弄");
        activiesDataModel3.setPopdb_id(215637);
        activiesDataModel3.setStart_time("12:40");
        activiesDataModel3.setEnd_time("14:30");

        ActiviesDataModel activiesDataModel4 = new ActiviesDataModel();
        activiesDataModel4.setPop_name(" POP Name4 淘宝天猫超市");
        activiesDataModel4.setPop_address("南京东路1024弄");
        activiesDataModel4.setPopdb_id(215636);
        activiesDataModel4.setStart_time("15:40");
        activiesDataModel4.setEnd_time("17:30");


原文地址:https://blog.csdn.net/caijinghuacaijinghua/article/details/144420191

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!