Android開發自定義控制元件實現一個球賽勝負數統計條

王世暉發表於2016-05-12

效果如下圖所示,展示兩個球隊交戰勝負資訊

首先此控制元件在水平方向均分為5份,第一份和第五份留白不繪製內容

第二三四份分別繪製3列資料

垂直方向分為N份,N和輸入資料的最大值有關

垂直方向下邊百分之二十的空間顯示文字,上邊百分之八十的空間顯示指定數量的橫線,橫線上方顯示橫線的數量

因為垂直方向做了N等分,因此垂直方向相當於有了一個刻度,經過計算每條橫線繪製在屬於自己的刻度處即可



完整程式碼如下:

public class GameOutcomeBar extends View {
    private Context context;
    /*y方向的刻度,資料越多,刻度值越小*/
    private int MAX_GRADE=20;
    /*記錄 勝場 平局 負場 畫筆顏色*/
    private int mWinColor;
    private int mDrawColor;
    private int mLoseColor;
    /*勝場 平局 負場 數量*/
    private int mWins;
    private int mDraws;
    private int mLoses;
    private TypedValue typedValue;
    /*繪製圖形的畫筆*/
    private Paint paintBar = new Paint();
    /*繪製文字的畫筆*/
    private Paint paintText = new Paint();
    public GameOutcomeBar(Context context) {
        super(context);
        this.context=context;
        init();
    }

    public GameOutcomeBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context=context;
        init();
    }

    public GameOutcomeBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context=context;
        init();
    }



    private void init() {
        /*資料初始化*/
        mWinColor = Color.BLUE;
        mDrawColor =Color.YELLOW;
        mLoseColor =Color.GREEN;
        mWins =0;
        mDraws =0;
        mLoses =0;
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        /*總寬度*/
        float totalWidth =getWidth();
        /*除了下邊文字以外的高度,下邊文字佔據的高度是總高度的百分之二十*/
        float totalBarHeight =getHeight()*0.8f;
        /*畫筆大小的標準*/
        float paintSize = DensityUtil.dip2px(getContext(),100);
        /*控制元件整個寬度分為5列,第一列和第五列留白,第二三四列分別繪製勝場、平局和負場*/
        float columnLength = totalWidth /5;
        /*三列之間的間距*/
        float columnSpan = totalWidth /40;

        /*繪製橫線的畫筆設定*/
        paintBar.reset();
        paintBar.setStrokeWidth(paintSize * 1f/2 / MAX_GRADE / 3);
        paintBar.setStyle(Paint.Style.STROKE);
        paintBar.setAntiAlias(true);
        /*繪製勝場*/
        paintBar.setColor(mWinColor);
        /*迴圈繪製橫線*/
        for (int i = 0; i< mWins; i++) {
            /*計算每一條橫線的垂直座標位置*/
            float eachLineHeight=totalBarHeight * (1f-(i+2f) / MAX_GRADE);
            /*合適的位置開始繪製橫線*/
            canvas.drawLine(totalWidth * 1 / 5 - columnSpan,eachLineHeight ,
                    totalWidth * 2 / 5 - columnSpan, eachLineHeight,paintBar);
        }
        /*繪製文字畫筆設定*/
        paintText.reset();
        paintText.setStyle(Paint.Style.STROKE);
        paintText.setAntiAlias(true);
        /*文字從中間開始繪製*/
        paintText.setTextAlign(Paint.Align.CENTER);
        typedValue=new TypedValue();
        /*設定文字畫筆顏色*/
        context.getTheme().resolveAttribute(R.attr.maintextclor, typedValue,true);
        paintText.setColor(getResources().getColor(typedValue.resourceId));
        /*設定文字畫筆大小*/
        paintText.setTextSize(paintSize / 5);
        /*繪製文字,在橫線列的最上方繪製數字*/
        canvas.drawText("" + mWins, totalWidth * 1 / 5 - columnSpan + columnLength /2, totalBarHeight * (1f- (mWins +2f) / MAX_GRADE), paintText);
        /*更改文字畫筆大小,在橫線列的下方繪製文字*/
        paintText.setTextSize(paintSize / 15);
        Paint.FontMetrics fontMetrics = paintText.getFontMetrics();
        canvas.drawText("勝場" , totalWidth * 1 / 5 - columnSpan + columnLength /2, totalBarHeight-fontMetrics.top, paintText);

        /*繪製平局*/
        paintBar.setColor(mDrawColor);
        for (int i = 0; i< mDraws; i++) {
            float eachLineHeight=totalBarHeight * (1f-(i+2f) / MAX_GRADE);
            canvas.drawLine(totalWidth * 2 / 5 , eachLineHeight,
                    totalWidth * 3 / 5  , eachLineHeight,paintBar);
        }
        paintText.setTextSize(paintSize / 5);
        canvas.drawText("" + mDraws, totalWidth * 2 / 5 + columnLength / 2, totalBarHeight * (1f - (mDraws +2f) / MAX_GRADE), paintText);
        paintText.setTextSize(paintSize / 15);
        fontMetrics = paintText.getFontMetrics();
        canvas.drawText("平局" , totalWidth * 2 / 5+ columnLength /2, totalBarHeight -fontMetrics.top, paintText);

        /*繪製負場*/
        paintBar.setColor(mLoseColor);
        for (int i = 0; i< mLoses; i++) {
            float eachLineHeight=totalBarHeight * (1f-(i+2f) / MAX_GRADE);
            canvas.drawLine(totalWidth * 3 / 5 + columnSpan, eachLineHeight,
                    totalWidth * 4 / 5 + columnSpan, eachLineHeight,paintBar);
        }
        paintText.setTextSize(paintSize / 5);
        canvas.drawText("" + mLoses, totalWidth * 3 / 5 + columnSpan + columnLength /2, totalBarHeight * (1f - (mLoses +2f) / MAX_GRADE), paintText);
        paintText.setTextSize(paintSize / 15);
        fontMetrics = paintText.getFontMetrics();
        canvas.drawText("負場" , totalWidth * 3 / 5 + columnSpan + columnLength /2, totalBarHeight-fontMetrics.top, paintText);
    }

    public void setWinsDrawLose(int wins,int draw, int lose) {
        if (wins<0||draw<0||lose<0) {
            throw new IllegalArgumentException("引數不能小於零");
        }
        this.mWins =wins;
        this.mDraws =draw;
        this.mLoses =lose;
        this.MAX_GRADE=Math.max(wins,Math.max(draw,lose))+15;
        this.invalidate();
    }
}



相關文章