自定義View之簽到足跡控制元件

davidtim發表於2021-09-09

大家好我叫王大錘,今天 UI 妹紙又給了個圖叫我做,我一看是這樣的:

圖片描述

輸入圖片說明


儘管嘴上說著不願意,但是身體還是很誠實,開始擼程式碼了。


我們首先把這個控制元件劃分成 1個 部分:

  • 1.底下部分的直線

  • 2.左右兩邊的半圓弧度

  • 3.線上面的小圖示

  • 4.最後的文字說明

我不管,我就要說一個

首先我們把線畫出來,大概這個樣子


圖片描述

輸入圖片說明

    @Override
    protected void onDraw(Canvas canvas)
    {
        paint.setColor(backColor);
        paint.setStrokeWidth(strokeWidth);        int rowCount = (monthDays % 7 == 0 ? monthDays / 7 : monthDays / 7 + 1);        int rowHeigh = height / (rowCount);        int startX = 0 + rowHeigh / 2;        int endX = width - rowHeigh / 2;        int days = 0;        for (int a = 0; a 

我們這裡根據一個月得總天數,和一條線上需要畫七個圖,計算出總共需要畫出的線條數,以及畫出左邊和右邊的弧度,根據當前線是單數還是雙數,來計算出是否是左半邊的弧度,還是右半邊的弧度,以及是否是最後的一條線,因為最後一條線不需要畫弧度。


然後再線上上畫出禮物數量

            // 這裡是來判斷,本次這根線上畫出的禮物的點,以及順序是順畫,還是倒畫出。
            bitmapList.clear();            for (int b = 0; b 

這裡有一個需要注意的地方,就是,線上為雙數的時候,這時候禮物的排列是需要反過來排列的,我這裡使用了一個LinkedList來儲存禮物的排列順序,然後我們透過計算平均數,計算出每個禮物的位置。

    /**
     * 畫出的按路線上的圖片,勾選,禮物
     * @param bitmapList
     * @param startX
     * @param endX
     * @param y
     * @param canvas
     */
    private void drawImgs(List bitmapList, float startX, float endX, float y, Canvas canvas)
    {
        startX = startX - bitmapList.get(0).getWidth() / 2;        int count = bitmapList.size();        float bitmap_width = (endX - startX) / (count - 1);        for (int a = 0; a 

這裡也有一個需要注意的地方,就是,當最後一條線是短的時候,這個時候,你的禮物的排列需要按照那條線的開始位置和結束位置來平均計算每個禮物的位置。


最後,我們在最後一條線最後的位置,畫出文字

/**
     * 畫出文字
     * @param canvas
     * @param y
     * @param x
     */
    private void drawText(Canvas canvas, float y, float x)
    {        int oldColor = paint.getColor();
        Paint.Style old_style = paint.getStyle();

        paint.setStyle(Paint.Style.FILL);
        paint.setColor(textColor);
        String drawText = "已累計簽到"+signInCount+"天";
        paint.setTextSize(DensityUtil.sp2px(getContext(), 15));        int textHeigh = getStringHeight(drawText);        int textWidth = getStringWidth(drawText);
        canvas.drawText(drawText, x + textWidth/2, y + textHeigh / 2, paint);

        paint.setColor(oldColor);
        paint.setStyle(old_style);
    }

圖片描述

輸入圖片說明


好了,這就是所有的思路。下面貼一下最新完整程式碼(更新時間 2018年2月5日):

import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.RectF;import android.support.annotation.Nullable;import android.util.AttributeSet;import android.view.View;import com.yongxing.QianJR.R;import com.yongxing.QianJR.utils.DensityUtil;import java.util.LinkedList;import java.util.List;/**
 * Created by xiaolei on 2017/11/6.
 */public class SignInView extends View{    private int width, height;    private int monthDays = 31;//本月有31天
    private Paint paint;    private RectF oval = new RectF();    private float strokeWidth = 10;    private Bitmap checkBitmap, uncheckBitmap, closeGiftBitmap, openGiftBitmap;    private int backColor = Color.parseColor("#C3DEEA"),
            rashColor = Color.parseColor("#B2CADB"),
            textColor = Color.parseColor("#60ADE5");    private List bitmapList = new LinkedList();    private int signInCount = 9;    public SignInView(Context context)
    {        this(context, null);
    }    public SignInView(Context context, @Nullable AttributeSet attrs)
    {        this(context, attrs, 0);
    }    public SignInView(Context context, @Nullable AttributeSet attrs, int defStyleAttr)
    {        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }    private void init(Context context, AttributeSet attrs)
    {
        paint = new Paint();
        paint.setAntiAlias(true);
        strokeWidth = DensityUtil.dip2px(context, 6);
        checkBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon_sign_in_check_img);
        uncheckBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon_sign_in_uncheck_img);
        closeGiftBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon_close_gift_img);
        openGiftBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon_open_gift_img);
    }    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        height = MeasureSpec.getSize(heightMeasureSpec);
        width = MeasureSpec.getSize(widthMeasureSpec);        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }    /**
     * 設定本月天數
     *
     * @param monthDays
     */
    public void setMonthDays(int monthDays)
    {        this.monthDays = monthDays;        if (monthDays == 0)
        {            this.monthDays = 31;
        }
        postInvalidate();
    }    /**
     * 設定一共簽到了幾天
     *
     * @param days
     */
    public void setProgress(int days)
    {        this.signInCount = days;
        postInvalidate();
    }    @Override
    protected void onDraw(Canvas canvas)
    {
        paint.setColor(backColor);
        paint.setStrokeWidth(strokeWidth);        int rowCount = (monthDays % 7 == 0 ? monthDays / 7 : monthDays / 7 + 1);        int rowHeigh = height / (rowCount);        int startX = 0 + rowHeigh / 2;        int endX = width - rowHeigh / 2;        int days = 0;        for (int a = 0; a  bitmapList, float startX, float endX, float y, Canvas canvas)
    {         if (!bitmapList.isEmpty())
        {
            startX = startX - bitmapList.get(0).getWidth() / 2;            int count = bitmapList.size();            float bitmap_width = (endX - startX) / (count - 1);            for (int a = 0; a 

THE END



作者:xiaolei123
連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3349/viewspace-2809974/,如需轉載,請註明出處,否則將追究法律責任。

相關文章