Android Gantt View 安卓实现项目甘特图

需要做一个项目管理工具,其中使用到了甘特图。发现全网甘特图解决方案比较少,于是自动动手丰衣足食。

前面我用 Python和 Node.js 前端都做过,这次仅仅是移植到 Android上面。

其实甘特图非常简单,开发也不难,如果我专职去做,能做出一个非常棒产品。我写这个只是消遣,玩玩,闲的蛋痛,所以不怎么上心,就搞成下面这德行吧。仅仅供大家学习,参考。

那天心情好了,完善一下。

屏幕布局文件

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </ScrollView>

    <HorizontalScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">


        <cn.netkiller.gantt.ui.GanttView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:background="#DEDEDE"
            android:keepScreenOn="true"
            android:padding="15dp"
            android:text="TextView" />
    </HorizontalScrollView>


</androidx.constraintlayout.widget.ConstraintLayout>

View 代码

package cn.netkiller.gantt.ui;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * TODO: document your custom view class.
 */
public class GanttView extends View {
    private final String TAG = GanttView.class.getSimpleName();
    private Drawable mExampleDrawable;

    private int contentWidth, contentHeight;
    private int paddingLeft, paddingTop, paddingRight, paddingBottom;
    private int canvasLeft, canvasTop, canvasRight, canvasBottom;
    private Canvas canvas;
    private int textSize;
    private Map<Date, Coordinate> coordinates = new HashMap<Date, Coordinate>();


    public static class Coordinate {
        public int x, y;

        public Coordinate(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public int getX() {
            return x;
        }

        public void setX(int x) {
            this.x = x;
        }

        public int getY() {
            return y;
        }

        public void setY(int y) {
            this.y = y;
        }

        @Override
        public String toString() {
            return "Coordinate{" +
                    "x=" + x +
                    ", y=" + y +
                    '}';
        }
    }

    public GanttView(Context context) {
        super(context);
        init(null, 0);
    }

    public GanttView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs, 0);
    }

    public GanttView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(attrs, defStyle);
    }

    private void init(AttributeSet attrs, int defStyle) {

        paddingLeft = getPaddingLeft();
        paddingTop = getPaddingTop();
        paddingRight = getPaddingRight();
        paddingBottom = getPaddingBottom();

        contentWidth = getWidth() - paddingLeft - paddingRight;
        contentHeight = getHeight() - paddingTop - paddingBottom;

        // Load attributes
//        final TypedArray a = getContext().obtainStyledAttributes(
//                attrs, R.styleable.MyView, defStyle, 0);
//
        mExampleString = a.getString(
                R.styleable.MyView_exampleString);
//        mExampleString = "AAAA";
//        mExampleColor = a.getColor(
//                R.styleable.MyView_exampleColor,
//                mExampleColor);
//        // Use getDimensionPixelSize or getDimensionPixelOffset when dealing with
//        // values that should fall on pixel boundaries.
//        mExampleDimension = a.getDimension(
//                R.styleable.MyView_exampleDimension,
//                mExampleDimension);
//
//        if (a.hasValue(R.styleable.MyView_exampleDrawable)) {
//            mExampleDrawable = a.getDrawable(
//                    R.styleable.MyView_exampleDrawable);
//            mExampleDrawable.setCallback(this);
//        }
//
//        a.recycle();

    }

//    @Override
//    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//        super.onSizeChanged(w, h, oldw, oldh);
//
        if (h < computeVerticalScrollRange()) {
            canScroll = true;
        } else {
            canScroll = false;
        }
//    }

    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(contentWidth, contentHeight);

    }
//
//    private boolean canScroll = true;
//
//    @Override
//    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//        super.onSizeChanged(w, h, oldw, oldh);
//
//        if (h < computeVerticalScrollRange()) {
//            canScroll = true;
//        } else {
//            canScroll = false;
//        }
//    }

    List<Data> taskList = List.of(
            new Data("AAA", "2024-06-28", "2024-07-04", "1", "Neo"),
            new Data("AAABBB", "2024-06-15", "2024-06-20", "10", "Neo"),
            new Data("AAACC", "2024-06-25", "2024-06-27", "1", "Neo"),
            new Data("AAABBCCD", "2024-06-25", "2024-06-28", "1", "Neo"),
            new Data("消息推送", "2024-01-15", "2024-06-30", "1", "Neo"),
            new Data("AAA", "2024-06-05", "2024-07-12", "1", "Neo"),
            new Data("AAA", "2024-06-05", "2024-07-17", "1", "Neo"),
            new Data("AAA", "2024-06-15", "2024-07-07", "1", "Neo"),
            new Data("AAA", "2024-06-18", "2024-07-02", "1", "Neo"),
            new Data("AAA", "2024-06-05", "2024-07-05", "1", "Neo")
    );

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        this.canvas = canvas;

        canvasTop = paddingTop;
        canvasLeft = paddingLeft;
        canvasRight = canvas.getWidth() - paddingRight;
        canvasBottom = canvas.getHeight() - paddingBottom;


        Paint paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(Color.BLUE);
        paint.setStrokeWidth(2);

        canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
        paint.setColor(Color.DKGRAY);
        paint.setStyle(Paint.Style.FILL_AND_STROKE);
        paint.setAlpha(30);
        canvas.drawRect(canvasLeft, canvasTop, canvasRight, canvasBottom, paint);

        title("canvas");
        try {
            calendar("2024-06-12", "2024-07-20");
            tasks(taskList);
        } catch (Exception e) {

        }

        // Draw the example drawable on top of the text.
        if (mExampleDrawable != null) {
            mExampleDrawable.setBounds(paddingLeft, paddingTop,
                    paddingLeft + contentWidth, paddingTop + contentHeight);
            mExampleDrawable.draw(canvas);
        }


    }


    public Map<String, Float> colume(List<Data> taskList) {
        TextPaint textPaint = new TextPaint();
        textPaint.setTextSize(sp2px(20));


        float name = textPaint.measureText("任务");
        float start = textPaint.measureText("开始日期");
        float finish = textPaint.measureText("截止日期");
        float day = textPaint.measureText("工时");
        float resource = textPaint.measureText("资源");
        for (Data data : taskList) {
            float textWidth = textPaint.measureText(data.name);
            if (textWidth > name) {
                name = textWidth;
            }

            if (textPaint.measureText(data.start) > start) {
                start = textPaint.measureText(data.start);
            }
            if (textPaint.measureText(data.finish) > finish) {
                finish = textPaint.measureText(data.finish);
            }
            if (textPaint.measureText(data.day) > day) {
                day = textPaint.measureText(data.day);
            }
            if (textPaint.measureText(data.resource) > resource) {
                resource = textPaint.measureText(data.resource);
            }
        }

        float finalName = name;
        float finalStart = start;
        float finalResource = resource;
        float finalFinish = finish;
        float finalDay = day;
        return new LinkedHashMap<String, Float>() {{
            put("任务", finalName);
            put("开始日期", finalStart);
            put("截止日期", finalFinish);
            put("工时", finalDay);
            put("资源", finalResource);
        }};

    }

    private int titleHeight;

    public float sp2px(float spValue) {
        //fontScale (DisplayMetrics类中属性scaledDensity)
        final float fontScale = getResources().getDisplayMetrics().scaledDensity;
        return (spValue * fontScale + 0.5f);
    }

    private void title(String value) {
        // Draw the text.
        TextPaint textPaint = new TextPaint();
        textPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
        textPaint.setTextAlign(Paint.Align.LEFT);

        textPaint.setTextSize(sp2px(25));
        float textWidth = textPaint.measureText(value);

        Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
//        float textHeight = fontMetrics.bottom;
        float textHeight = textPaint.getFontSpacing();
        canvas.drawText(value,
                canvasLeft + (getWidth() - textWidth) / 2,
                canvasTop + textHeight,
                textPaint);

        textPaint.setTextSize(sp2px(18));

        String copyright = "https://www.netkiller.cn - design by netkiller";
        textWidth = textPaint.measureText(copyright);
        textHeight += textPaint.getFontSpacing();
        canvas.drawText(copyright,
                getWidth() - textWidth - canvasLeft,
                canvasTop + textHeight,
                textPaint);

        titleHeight = (int) textHeight;

    }

    private void process(String string, int x, int y, int size) {
        TextPaint mTextPaint = new TextPaint();
        mTextPaint.setTextSize(sp2px(size));
//        mTextWidth = mTextPaint.measureText(string);
//        Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
//        mTextHeight = fontMetrics.bottom;

    }

    private int tableEnd = 0;

//    private void table() {
//
//
        TextPaint textPaint = new TextPaint();
//        calendarTextPaint.setTextSize(sp2px(20));
//
//        Paint.FontMetrics fontMetrics = calendarTextPaint.getFontMetrics();
//        float fontSpacing = calendarTextPaint.getFontSpacing();
        mTextHeight = fontMetrics.bottom;
//        int textX = canvasLeft + (int) fontSpacing / 2;
//        int textY = canvasTop + (int) fontSpacing * 3 + titleHeight;
//
//        int startX = 0;
//        int startY = (int) (canvasTop + titleHeight + fontSpacing * 2);
//        int stopX = startX;
//        int stopY = canvasBottom;
//
//        for (String text : List.of("任务", "开始日期", "截止日期", "工时", "资源")) {
//            canvas.drawText(text, textX, textY, calendarTextPaint);
//            textX += (int) (calendarTextPaint.measureText(text) + fontSpacing);
//            startX = stopX = textX;
//            canvas.drawLine(startX - (fontSpacing / 2), startY, stopX - (fontSpacing / 2), stopY, calendarPaint);
//        }
//        tableEnd = (int) (startX - (int) fontSpacing - fontSpacing / 2);
//
//    }

    private void table() {


//        TextPaint textPaint = new TextPaint();
        calendarTextPaint.setTextSize(sp2px(20));

//        Paint.FontMetrics fontMetrics = calendarTextPaint.getFontMetrics();
        float fontSpacing = calendarTextPaint.getFontSpacing();
//        mTextHeight = fontMetrics.bottom;

        int tableLeft = canvasLeft;
        int tableTop = canvasTop + (int) fontSpacing * 2 + titleHeight;
        int tableRight = canvasRight;
        int tableBottom = canvasBottom;


        int textX = tableLeft;
        int textY = tableTop + calendarFontSpacing;

        int startX = tableLeft;
        int startY = tableTop;
        int stopX = startX;
        int stopY = tableBottom;


        for (Map.Entry<String, Float> entry : colume(taskList).entrySet()) {
            String text = entry.getKey();
            Float textWidth = entry.getValue();
            canvas.drawText(text, textX + (int) fontSpacing / 2, textY, calendarTextPaint);

            textX += (int) (textWidth + calendarFontSpacing);
            startX += (int) (textWidth + calendarFontSpacing);
            stopX = startX;
            canvas.drawLine(startX, startY, stopX, stopY, calendarPaint);
        }
        tableEnd = tableRight = (int) (startX - calendarFontSpacing / 2);

    }

    private void tasks(List<Data> taskList) throws ParseException {

        Paint paint = new Paint();
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.BLUE);
        paint.setStrokeWidth(2);

//        TextPaint textPaint = new TextPaint();
//        calendarPaint.setColor(Color.DKGRAY);
        calendarPaint.setColor(Color.GRAY);
        calendarTextPaint.setTextSize(sp2px(20));

        int taskTop = calendarTop + calendarFontSpacing * 3;
        int taskLeft = canvasLeft;
        int taskRight = tableEnd;
        int taskBottom = canvasBottom;

//        Paint.FontMetrics fontMetrics = calendarTextPaint.getFontMetrics();
//        float fontSpacing = calendarTextPaint.getFontSpacing();

        int textX = 0;
        int textY = taskTop + calendarFontSpacing;

        int startX = 0;
        int startY = taskTop;
        int stopX = startX;
        int stopY = taskTop + calendarFontSpacing;

//        canvas.drawLine(startX, calendarTop + calendarFontSpacing * 1, calendarRight, calendarTop + calendarFontSpacing * 1, calendarPaint);
//        canvas.drawLine(startX, startY - calendarFontSpacing, startX, stopY, calendarTextPaint);
        Map<String, Float> col = colume(taskList);
        Log.d(TAG, col.toString());

        for (Data task : taskList) {
            textX = taskLeft + (int) calendarFontSpacing / 2;
            Iterator<Float> aa = col.values().iterator();
            for (String text : List.of(task.name, task.start, task.finish, task.day, task.resource)) {

                Float textWidth = aa.next();
                canvas.drawText(text, textX, textY, calendarTextPaint);
                textX += (int) (textWidth + calendarFontSpacing);
                startX = stopX = textX;
            }
            textY += (int) (calendarFontSpacing);

            try {


                Date startData = new SimpleDateFormat("yyyy-MM-dd").parse(task.start);
                Date finishData = new SimpleDateFormat("yyyy-MM-dd").parse(task.finish);
                Log.e(TAG, "Start: " + String.valueOf(startData) + " Finish: " + finishData);
                Coordinate startCoordinates = coordinates.get(startData);
                Coordinate finishCoordinates = coordinates.get(finishData);
                Log.e(TAG, "Start: " + startCoordinates.toString() + "Finish: " + finishCoordinates);
                canvas.drawRect(startCoordinates.x + 5, startY + 5, finishCoordinates.x + calendarFontSpacing - 5, stopY - 5, paint);

            } catch (Exception e) {

            }
//            canvas.drawText(task.name, textX, textY, calendarTextPaint);
            startY += (int) (calendarFontSpacing);

            canvas.drawLine(canvasLeft, startY, calendarRight, stopY, calendarPaint);
            stopY += (int) (calendarFontSpacing);
        }

    }


    private Paint calendarPaint = new Paint();
    private TextPaint calendarTextPaint = new TextPaint();
    private int calendarFontSpacing;
    private int calendarLeft, calendarTop, calendarRight, calendarBottom;

    private void calendar(String startDate, String endDate) throws ParseException {


        calendarPaint.setStyle(Paint.Style.STROKE);
        calendarPaint.setColor(Color.DKGRAY);
        calendarPaint.setStrokeWidth(2);
//        calendarPaint.setTextSize(sp2px(20));
//        paint.setAlpha(50);
        calendarTextPaint.setTextSize(sp2px(20));
        calendarFontSpacing = (int) calendarTextPaint.getFontSpacing();

//
//        Paint paint = new Paint();
//        paint.setTypeface(Typeface.DEFAULT);
//        paint.setTextSize(getTextSize());
//        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
//        float textHeight = fm.getAscent() + fm.getDescent();

//        float calendarFontSpacing = fontMetrics.descent - fontMetrics.ascent;
//        float calendarFontSpacing = fontMetrics.bottom - fontMetrics.top;


//        Paint.FontMetrics fontMetrics = calendarPaint.getFontMetrics();
//        float textHeight = fontMetrics.getAscent() + fontMetrics.getDescent();
        // 边框
        canvas.drawRect(canvasLeft, canvasTop + titleHeight, canvasRight, canvasBottom, calendarPaint);
        table();

        calendarLeft = canvasLeft + tableEnd;
        calendarTop = canvasTop + titleHeight;
        calendarRight = canvasRight;
        calendarBottom = canvasBottom;


        int textX = calendarLeft;
        int textY = calendarTop + (int) calendarFontSpacing * 2;

        int startX = calendarLeft;
        int startY = calendarTop + (int) calendarFontSpacing * 1;
        int stopX = 0;
        int stopY = calendarBottom;
        canvas.drawLine(startX, calendarTop + calendarFontSpacing * 1, calendarRight, calendarTop + calendarFontSpacing * 1, calendarPaint);
        canvas.drawLine(startX, startY - calendarFontSpacing, startX, stopY, calendarTextPaint);

        canvas.drawLine(canvasLeft, calendarTop + calendarFontSpacing * 2, calendarRight, calendarTop + calendarFontSpacing * 2, calendarPaint);
        canvas.drawLine(canvasLeft, calendarTop + calendarFontSpacing * 3, canvasRight, calendarTop + calendarFontSpacing * 3, calendarPaint);

//        Paint paint = new Paint();
        calendarPaint.setStyle(Paint.Style.FILL);
        calendarPaint.setColor(Color.BLUE);
        calendarPaint.setStrokeWidth(2);

        startY = calendarTop + (int) calendarFontSpacing * 2;

        int measureWeek = (int) calendarTextPaint.measureText("六");
        int measureDay = (int) calendarTextPaint.measureText("30");

        int measureText = measureWeek > measureDay ? measureWeek : measureDay;
        List<String> weeks = List.of("日", "一", "二", "三", "四", "五", "六");

        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");

        Date d1 = new SimpleDateFormat("yyyy-MM-dd").parse(startDate);//定义起始日期
        Date d2 = new SimpleDateFormat("yyyy-MM-dd").parse(endDate);//定义结束日期

        calendar.setTime(d2);
        calendar.add(Calendar.DATE, 1);
        d2 = calendar.getTime();

        calendar.setTime(d1);//设置日期起始时间

        while (calendar.getTime().before(d2)) {//判断是否到结束日期
            String month = new SimpleDateFormat("yyyy-MM").format(calendar.getTime());
            String day = new SimpleDateFormat("d").format(calendar.getTime());
            coordinates.put(calendar.getTime(), new Coordinate(startX, startY));
//            if (dateRange.containsKey(month)) {
//                List<Date> tmp = dateRange.get(month);
//                tmp.add(calendar.getTime());
//            } else {
//                dateRange.put(month, List.of(calendar.getTime()));
//            }
            int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
            String week = weeks.get(dayOfWeek - 1);


            if (Set.of("六", "日").contains(week)) {
                calendarPaint.setColor(Color.WHITE);
            } else {
                calendarPaint.setColor(Color.GRAY);
            }
//            Log.d(TAG, String.valueOf());
//            Log.d(TAG, String.valueOf());
            stopX = (int) (startX + measureText);
            canvas.drawRect(startX, startY, stopX, stopY, calendarPaint);
            canvas.drawText(week, textX, textY, calendarTextPaint);
            if (calendarTextPaint.measureText(day) < calendarTextPaint.measureText(week)) {
                canvas.drawText(day, textX + calendarTextPaint.measureText(day) / 2, textY + calendarFontSpacing, calendarTextPaint);
            } else {
                canvas.drawText(day, textX, textY + calendarFontSpacing, calendarTextPaint);
            }
            if (day.equals("1")) {
                canvas.drawText(month, textX, textY - calendarFontSpacing, calendarTextPaint);
                canvas.drawLine(startX, startY - calendarFontSpacing * 2, startX, stopY, calendarTextPaint);
            }

            if (week.equals("日")) {
                canvas.drawLine(stopX, startY - calendarFontSpacing, stopX, stopY, calendarTextPaint);
            }

            textX += measureText + 2;
            startX = textX;


            calendar.add(Calendar.DATE, 1);//进行当前日期月份加1
        }
        calendarPaint.setColor(Color.GRAY);
        canvas.drawLine(canvasLeft, calendarTop + calendarFontSpacing * 2, calendarRight, calendarTop + calendarFontSpacing * 2, calendarPaint);
        canvas.drawLine(canvasLeft, calendarTop + calendarFontSpacing * 3, canvasRight, calendarTop + calendarFontSpacing * 3, calendarPaint);


        calendarLeft = stopX;

    }


    public class Data {
        public Data(String name, String start, String finish, String day, String resource) {
            this.name = name;
            this.start = start;
            this.finish = finish;
            this.day = day;
            this.resource = resource;
        }

        public String name;
        public String start;
        public String finish;
        public String day;
        public String resource;
    }
//    public class Coordinate{
//
//    }

    public void setTextSize(int textSize) {
        this.textSize = textSize;
    }

    public int getTextSize() {
        return textSize;
    }

    /**
     * Gets the example dimension attribute value.
     *
     * @return The example dimension attribute value.
     */
//    public float getExampleDimension() {
//        return mExampleDimension;
//    }

    /**
     * Sets the view"s example dimension attribute value. In the example view, this dimension
     * is the font size.
     *
     * @param exampleDimension The example dimension attribute value to use.
     */
//    public void setExampleDimension(float exampleDimension) {
//        mExampleDimension = exampleDimension;
//        invalidateTextPaintAndMeasurements();
//    }

    /**
     * Gets the example drawable attribute value.
     *
     * @return The example drawable attribute value.
     */
//    public Drawable getExampleDrawable() {
//        return mExampleDrawable;
//    }

    /**
     * Sets the view"s example drawable attribute value. In the example view, this drawable is
     * drawn above the text.
     *
     * @param exampleDrawable The example drawable attribute value to use.
     */
//    public void setExampleDrawable(Drawable exampleDrawable) {
//        mExampleDrawable = exampleDrawable;
//    }
    private void week() {

        Paint paint = new Paint();
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.BLUE);
        paint.setStrokeWidth(2);


//        Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
//        float fontSpacing = calendarTextPaint.getFontSpacing();

        int textX = calendarLeft;
        int textY = calendarTop + (int) calendarFontSpacing * 2;

        int startX = calendarLeft;
        int startY = calendarTop + (int) calendarFontSpacing * 2;
        int stopX = 0;
        int stopY = calendarBottom;

        int measureWeek = (int) calendarTextPaint.measureText("六");
        int measureDay = (int) calendarTextPaint.measureText("30");

        int measureText = measureWeek > measureDay ? measureWeek : measureDay;
        List<String> weeks = List.of("一", "二", "三", "四", "五", "六", "日");
        int w = 0;
        for (int i = 1; i <= 31; i++) {

//            for (String week : List.of("一", "二", "三", "四", "五", "六", "日")) {
            String week = weeks.get(w);
            w++;
            if (w >= weeks.size()) {
                w = 0;
            }
            String day = String.valueOf(i);

            if (Set.of("六", "日").contains(week)) {
                paint.setColor(Color.WHITE);

            } else {
                paint.setColor(Color.GRAY);
            }
//            Log.d(TAG, String.valueOf());
//            Log.d(TAG, String.valueOf());
            stopX = (int) (startX + measureText);
            canvas.drawRect(startX, startY, stopX, stopY, paint);
            canvas.drawText(week, textX, textY, calendarTextPaint);
            if (calendarTextPaint.measureText(day) < calendarTextPaint.measureText(week)) {
                canvas.drawText(day, textX + calendarTextPaint.measureText(day) / 2, textY + calendarFontSpacing, calendarTextPaint);
            } else {
                canvas.drawText(day, textX, textY + calendarFontSpacing, calendarTextPaint);
            }
//                if (week.equals("一")) {
//                    canvas.drawLine(startX, startY - calendarFontSpacing, startX, stopY, calendarTextPaint);
//                }

            if (week.equals("日")) {
                canvas.drawLine(stopX, startY - calendarFontSpacing, stopX, stopY, calendarTextPaint);
            }

            textX += measureText + 2;
            startX = textX;
//            stopX = (int) (startX + fontSpacing);

        }


        calendarLeft = stopX;

    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

netkiller-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值