天天看點

imooc學習筆記--五子棋

imooc視訊位址

本次要練習的是自定義控件,并不是數學邏輯 ,是以主要的目的就是繪制棋盤。

養的貓咪跑丢了 郁悶ing….

首先看看效果圖,然後分析一下。

imooc學習筆記--五子棋

首先,背景圖 這個交給父容器

然後棋盤,可以分為兩部分,第一是線、 第二是棋子。

首先畫線的時候,肯定要求畫的是矩形,是以必須要以長和寬當中最小的那一方來作為棋盤的邊。

可以注意到有個細節是 在棋盤的左右離手機螢幕都有一定距離的。

棋盤是10*10的。

棋子落線上的交點上。

分析:

想要知道長和寬當中最小的那一方,前提是知道長和寬,擷取長和寬的方法

那麼擷取寬高可以這樣:

onMeasure方法中:

    int width_size = MeasureSpec.getSize(widthMeasureSpec);
    int height_size = MeasureSpec.getSize(heightMeasureSpec);

    Log.e("ASD", getMeasuredWidth() + "****" + getMeasuredHeight());
    Log.e("ASD", getWidth() + "++++" + getHeight());
    Log.e("ASD", width_size + "----" + height_size);
           

可是,這三個哪個是裝置寬高、哪個是擷取控件寬高呢?于是我測了一下:

<sunshine.myview2.MyView
        android:layout_width="100dp"
        android:layout_height="100px" />

- :: -/sunshine.myview2 E/ASD: ,
- :: -/sunshine.myview2 E/ASD: ,
- :: -/sunshine.myview2 E/ASD: ****
- :: -/sunshine.myview2 E/ASD: ++++
- :: -/sunshine.myview2 E/ASD: ----
- :: -/sunshine.myview2 E/ASD: ****
- :: -/sunshine.myview2 E/ASD: ++++
- :: -/sunshine.myview2 E/ASD: ----
- :: -/sunshine.myview2 E/ASD: ****
- :: -/sunshine.myview2 E/ASD: ++++
- :: -/sunshine.myview2 E/ASD: ----

- :: -/sunshine.myview2 E/ASD: ****
- :: -/sunshine.myview2 E/ASD: ++++
- :: -/sunshine.myview2 E/ASD: ----
           

打開程式時候控件是會不斷測量的(都這麼說我也就當成定理了),應該看最後測量的結果。

getMeasuredWidth()擷取的是200,getMeasuredHeight()擷取的是1118.

getWidth()擷取的是200,getHeight()擷取的是100.

width_size是200,height_size是100.

擷取到100的肯定都是像素了,擷取到200應該是由于螢幕密度的原因,由dp轉化為px時候是1:2的關系了,也就都是擷取本控件的大小(px)。

1118是什麼鬼呢,為啥前面是200,後面是1118!!!???

上網查了一下資料 覺得這裡說的很好這裡就不費時間了,主要内容如下:

①getMeasuredWidth方法獲得的值是setMeasuredDimension方法設定的值,它的值在measure方法運作後就會确定

②getWidth方法獲得是layout方法中傳遞的四個參數中的mRight-mLeft,它的值是在layout方法運作後确定的

③一般情況下在onLayout方法中使用getMeasuredWidth方法,而在除onLayout方法之外的地方用getWidth方法。

取兩者中最小的作為矩形的邊後(minWidth),我們發現還有個距離裝置邊框那邊距的問題(相對于控件是margin),我們将邊距預留為一份棋盤格子的minWidth,左右各1/2minWidth,也就是說我們畫線的時候要預留1/2minWidth的邊距。

畫線代碼(注意線的起點和重點,重複了就畫不出來了 =.= 由于不熟練,折騰了一番才出來):

@Override
    protected void onDraw(Canvas canvas) {
        for (int i = ; i < ; i++) {
            //橫線
            canvas.drawLine(
                    lineWidth / , (float) (( + i) * lineWidth),
                    minWidth - lineWidth / , (float) (( + i) * lineWidth),
                    paint_line);
            //縱線
            canvas.drawLine(
                    (float) (( + i) * lineWidth), lineWidth / ,
                    (float) (( + i) * lineWidth), minWidth - lineWidth / ,
                    paint_line);
        }
    }
           

費了一番力氣的效果圖(畫筆設定如下):

setBackgroundColor(0x99ff0000);

paint_line = new Paint();

paint_line.setColor(0xff00ff00);

paint_line.setStyle(Paint.Style.STROKE);

paint_line.setAntiAlias(true);

paint_line.setDither(true);

imooc學習筆記--五子棋

OK,下一步就是棋子了,要想顯示棋子首先得先加載棋子,加載時候要先設定棋子大小,棋子大小要在onSizeChanged中設定(為什麼呢,看方法名就能了解差不多了吧 - . - ),設定大小是用Bitmap.createScaledBitmap方法,一開始我寫錯成Bitmap.createBitmap了

createScaledBitmap(Bitmap src, int dstWidth, int dstHeight,boolean filter)

createBitmap(Bitmap source, int x, int y, int width, int height,Matrix m, boolean filter)

後來去看了下才知道Bitmap.createScaledBitmap也是調用的Bitmap.createBitmap方法。

加載完之後就要顯示出來啊,那怎麼顯示出來呢,肯定是觸發了之後顯示,那怎麼觸發呢,肯定找我們onTouchEvent(MotionEvent event)方法啊…..

@Override
    public boolean onTouchEvent(MotionEvent event) {
    //如果沒有ACTION_DOWN傳回true 就不會執行ACTION_UP,不知道為什麼
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            return true;
        }
        if (event.getAction() == MotionEvent.ACTION_UP) {
            Point point = new Point(
            (int) (event.getX() / lineWidth), (int) (event.getY() / lineWidth)
            );
            points.add(point);
            invalidate();//重繪
            return true;
        }
        return super.onTouchEvent(event);
    }
           

重繪後再onDraw中畫出棋子就Ok了

for (int i = ; i < points.size(); i++) {
            Log.e("asd", points.get(i).x + "---" + points.get(i).y);
            canvas.drawBitmap(stone_b,
                    (int) (lineWidth /  - lineWidth * ratio / ) + points.get(i).x * lineWidth,//x
                    (int) (lineWidth /  - lineWidth * ratio / ) + points.get(i).y * lineWidth,//y
                    null);
        }
           

看下最後的“成果”

imooc學習筆記--五子棋