imooc學習筆記--五子棋

imooc視頻地址

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

養的貓咪跑丟了 鬱悶ing….

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

這裏寫圖片描述
首先,背景圖 這個交給父容器
然後棋盤,可以分爲兩部分,第一是線、 第二是棋子。

首先畫線的時候,肯定要求畫的是矩形,所以必須要以長和寬當中最小的那一方來作爲棋盤的邊。
可以注意到有個細節是 在棋盤的左右離手機屏幕都有一定距離的。
棋盤是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" />

06-28 20:57:55.872 13720-13720/sunshine.myview2 E/ASD: 0,0
06-28 20:57:55.872 13720-13720/sunshine.myview2 E/ASD: 0,0
06-28 20:57:55.912 13720-13720/sunshine.myview2 E/ASD: 0****0
06-28 20:57:55.912 13720-13720/sunshine.myview2 E/ASD: 0++++0
06-28 20:57:55.912 13720-13720/sunshine.myview2 E/ASD: 200----1118
06-28 20:57:55.912 13720-13720/sunshine.myview2 E/ASD: 200****1118
06-28 20:57:55.912 13720-13720/sunshine.myview2 E/ASD: 0++++0
06-28 20:57:55.912 13720-13720/sunshine.myview2 E/ASD: 200----100
06-28 20:57:56.116 13720-13720/sunshine.myview2 E/ASD: 200****100
06-28 20:57:56.116 13720-13720/sunshine.myview2 E/ASD: 200++++100
06-28 20:57:56.116 13720-13720/sunshine.myview2 E/ASD: 200----1118

06-28 20:57:56.116 13720-13720/sunshine.myview2 E/ASD: 200****1118
06-28 20:57:56.116 13720-13720/sunshine.myview2 E/ASD: 200++++100
06-28 20:57:56.116 13720-13720/sunshine.myview2 E/ASD: 200----100

打開程序時候控件是會不斷測量的(都這麼說我也就當成定理了),應該看最後測量的結果。
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 = 0; i < 10; i++) {
            //橫線
            canvas.drawLine(
                    lineWidth / 2, (float) ((0.5 + i) * lineWidth),
                    minWidth - lineWidth / 2, (float) ((0.5 + i) * lineWidth),
                    paint_line);
            //縱線
            canvas.drawLine(
                    (float) ((0.5 + i) * lineWidth), lineWidth / 2,
                    (float) ((0.5 + i) * lineWidth), minWidth - lineWidth / 2,
                    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);

這裏寫圖片描述

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 = 0; i < points.size(); i++) {
            Log.e("asd", points.get(i).x + "---" + points.get(i).y);
            canvas.drawBitmap(stone_b,
                    (int) (lineWidth / 2 - lineWidth * ratio / 2) + points.get(i).x * lineWidth,//x
                    (int) (lineWidth / 2 - lineWidth * ratio / 2) + points.get(i).y * lineWidth,//y
                    null);
        }

看下最後的“成果”

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章