質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.99%

android drawRectの座標位置がおかしい 画面サイズを取得する二は?

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,638

ブロック崩しを作っています。
ボールが描画できたので、バーを描画したいです。

表示させること自体はできたのですが、位置がおかしいです。

座標でいうと、(0,0)の位置に表示されてしまいます。

bar  = new Bar( view_w/2 , view_h - 100 );

canvas.drawRect(bar.x, bar.y, 180, 10, paint);

bar = new Bar(500,500);

と引数を数字にするとバーも移動するのですが、画面サイズの違うスマホでも同じような位置に表示させたいので、画面サイズを取得して、変数に入れ、それをdrawRectの引数に使いたいです。

ちなみに、こちらを参考にしました。
リンク内容

リンク先ではOverrideされたsurfaceChangedの中に

view_w = width;
view_h = height;

があります。
Changedの中にあるのがいけないのかな?
と思い
surfaceCreatedの中に移動させても変わりませんでした。

Main

package com.example.blockbreak;

----中略----

public class MainActivity extends AppCompatActivity {



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //カスタムビュークラスのインスタンスをコンテントにセット
        setContentView(new CustomView(this));
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

    }

    class CustomView extends SurfaceView implements SurfaceHolder.Callback, Runnable {

        //スレッドクラス
        Thread mainLoop = null;
        // 描画用
        Paint paint = null;
        Paint paint2 = null;
        Paint paint3 = null;

        // 円のX,Y座標
        private int circleX = 50;
        private int circleY = 50;
        private int circle2X = 30;
        private int circle2Y = 30;
        // 円の移動量
        private int circleVx = 15;
        private int circleVy = 15;
        private int circle2Vx = 8;
        private int circle2Vy = 15;

        Bar  bar;              //バー
        private float touch_x; // タッチされたx座標
        int view_w, view_h;    // SurfaveViewの幅と高さ


        //コンストラクタ
        public CustomView(Context context) {
            super(context);
            // SurfaceView描画に用いるコールバックを登録する。
            getHolder().addCallback(this);
            // 描画用の準備
            paint = new Paint();
            paint2 = new Paint();
            paint3 = new Paint();
            paint.setColor(Color.RED);
            paint2.setColor(Color.CYAN);
            paint3.setColor(Color.GREEN);

        }

 @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
                                   int height) {
            // TODO 今回は何もしない。
            view_w = width;
            view_h = height;

        }


        // SurfaceView生成時に呼び出されるメソッド。
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            // 背景
            Canvas canvas = holder.lockCanvas();
            canvas.drawColor(Color.BLACK);
            holder.unlockCanvasAndPost(canvas);
            // スレッド開始
            mainLoop = new Thread(this);
            mainLoop.start();

            touch_x = view_w/2;
            //バーを生成
            bar  = new Bar( view_w/2 , view_h - 100 );


        }

----中略----


        @Override
        public void run(){

            while (true) {
                Canvas canvas = getHolder().lockCanvas();
                if (canvas != null)
                {
                    canvas.drawColor(Color.BLACK);
                    // 円1を描画する
                    canvas.drawCircle(circleX, circleY, 20, paint);
                    //円2を描画する
                    canvas.drawCircle(circle2X,circle2Y,20,paint2);
                    //長方形を描画する
                    canvas.drawRect(bar.x, bar.y, 180, 10, paint);


                    getHolder().unlockCanvasAndPost(canvas);

                   ----中略----

                }
            }





        }
    }





}


Barクラス

package com.example.blockbreak;

public class Bar {
    //表示座標
    public float x;
    public float y;
    //バーのサイズ
    public final float half_size = 100;

    //コンストラクタ
    public Bar( int _x, int _y ){
        //初期座標をセット
        x = (float)_x;
        y = (float)_y;
    }
    // 右移動
    public void right(float touch_x){
        x  = touch_x - half_size;
    }
    // 左移動
    public void left(float touch_x){
        x =  touch_x - half_size;
    }
}

追記
surfaceCreated の中で
view_w = canvas.getWidth();
view_h = canvas.getHeight();
しても値が0だった。

runの中で行っても値が0だった。

barのインスタンス化をrunの中に移し、
view_w = canvas.getWidth();
view_h = canvas.getHeight();
したら値取得できた。

@Override
        public void run(){

            while (true) {
                Canvas canvas = getHolder().lockCanvas();
                if (canvas != null)
                {
                    view_w = canvas.getWidth();
                    view_h = canvas.getHeight();

                    // バーを生成
                    bar  = new Bar( view_w/2 , view_h - 100 );
                    //長方形を描画する
                    canvas.drawRect( bar.x, bar.y , bar.x + 200 , bar.y + 20  , paint3);
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • dsuzuki

    2016/04/22 17:10

    view_w, view_hの値はどこで設定していますか?
    提示されたコードでは、変数定義時の初期値(ゼロ)しか読めません。

    キャンセル

  • masaakitsuyoshi

    2016/04/22 18:55

    surfaceChangedの引数にwidth, heightがあったのでこちらで定義したのですが、それでも初期値になっている?のでしょうか。

    キャンセル

  • masaakitsuyoshi

    2016/04/22 18:55

    surfaceChangedの部分追記しました。

    キャンセル

  • dsuzuki

    2016/04/22 19:11

    修正ありがとうございます。

    キャンセル

回答 3

check解決した方法

0

canvas.getWidth
canvas.getHeight
というのでSurfaceViewの画面サイズを取得できる。

取得した値を適当な変数に入れる。

view_w, view_hに入れれば良い。

しかし、それだけだと値がなぜか0のままだった。

view_w = canvas.getWidth();
view_h = canvas.getHeight();

// バーを生成
bar  = new Bar( view_w/2 , view_h - 100 );


barのインスタンス化をrunの中に移動させると、無事drawRectの引数に値がセットされた。(理由よくわからない)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

Canvas#drawRectの引数はleft,top,right,bottomです。
大小関係が矛盾していると0,0になったような気がします。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/22 18:59

    そうなんですね!
    リファレンスではleft top right bottomと書いてましたが、

    別のサイトでは

    drawRext(int x, int y, int width, int height)
    x y 座標と 四角形の横と高さ
    を示している、と書いてあり、混乱していました。

    キャンセル

  • 2016/04/22 19:26

    kotetuさんが回答しているとおり、view_w,view_hも怪しいので、drawRectの直前でログを出力して値を確認してください。

    キャンセル

  • 2016/04/23 21:08

    理屈がわかりませんが、barのインスタンス化する場所を変えたら正常に値が取得できました。

    キャンセル

0

surfaceCreatedの中でwidth,heightを表示してみてください。おそらく両方0のはずです。これは、
surfaceviewのライフサイクルが関係すると思われます。surfaceCreatedの中で画面サイズを取得したい場合、以下のようなコードで実現できます。だだし、これは画面全体のサイズでTitleBarや通知バーなども含まれてしまっているので、surfaceChanged内で取得できる画面サイズと異なる可能性があります。

Display display = getWindowManager().getDefaultDisplay();
 Point point = new Point();
 display.getSize(point);
//point.x 画面幅 
//point.y 画面の高さ

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/22 19:00

    調べてやってみます!

    キャンセル

  • 2016/04/23 20:24

    //display.getSize(point); の時点では point(0,0)

    point.x =720
    point.y = 1280

    view_w= 0
    view_h =0

    となっていました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.99%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる