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

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

ただいまの
回答率

88.22%

canvasのサイズをフルスクリーンにしたい。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,630

sunmo

score 10

AndroidのアプリでService上に配置したボタンをタップすると、画面のキャプチャをとり、特定の箇所に
DrawRectで矩形を付けたいのですが、スクリーン上のすべての領域を使用できず、
右端のエリアになると矩形が欠けて表示できないエリアがありました。

調べてみると、キャプチャで取得したbitmapのサイズとcanvasのサイズが異なることに気が付きました。
DrawRectでcanvasサイズを指定すると、やはり、右端部分に届いていませんでした。

サイズは下記の通りです。

画面サイズ:1080×1920
bitmapサイズ:1080×1794
canvasサイズ:840×1730

上記について、canvasサイズをbitmapサイズまたは画面サイズにすることはできますでしょうか?
どなたかご教示お願いいたします。

 該当のソースコード

package com.example.sumsu.overlaytest2;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.WindowManager;

public class AnalyzeResultView extends View {

    private Rect rect = null;
    private Paint mPaint = new Paint();
    private int displayWidth ;
    private int displayHeight ;

    public AnalyzeResultView(Context context) {
        super(context);
    }

    public AnalyzeResultView(Context context,AttributeSet attrs) {
        super(context,attrs);
    }

    public AnalyzeResultView(Context context, AttributeSet attrs, int defStyle){
        super(context, attrs, defStyle);
    }

    // 結果をセットし描画を更新するためのメソッド
    public void setAnalyzeResult(Rect rect) {
        this.rect = rect;

        postInvalidate();
    }

    /*@Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

        invalidate();
    }*/

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        // 画面の縦横サイズとdpを取得
        WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics displayMetrics = new DisplayMetrics();
        if(wm != null) {
            wm.getDefaultDisplay().getMetrics(displayMetrics);
        }
        displayWidth = displayMetrics.widthPixels;
        displayHeight = displayMetrics.heightPixels;

        setMeasuredDimension(displayWidth,displayHeight);

    }


    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);


        if(rect != null) {

            //描画のペイント定義
            mPaint.setAntiAlias(true);
            mPaint.setStrokeWidth(12);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setColor(Color.BLUE);

            // 矩形の描画処理...
            canvas.drawRect(rect, mPaint);
        }
    }

}
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:onClick="button1_click"
        android:text="@string/btnStart"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:onClick="button2_click"
        android:text="@string/btnEnd"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button" />
</android.support.constraint.ConstraintLayout>
overlay.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.example.sumsu.overlaytest2.AnalyzeResultView
        android:id="@+id/ResultView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>
overlay2.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linearLayout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="top|left"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/start"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="#99FF0000"
            android:text="Start" />

        <Button
            android:id="@+id/stop"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="#9900ff00"
            android:text="Stop" />

    </LinearLayout>

</LinearLayout>

 試したこと

2018/08/08 18:07追記
onMeasureを追加することで、Viewのサイズの変更ができました。
ただ、ナビゲーションバーとステータスバーのエリアは使用できませんでした。
こちらを使用することはできるのでしょうか?

2018/08/11 02:36追記
Viewのサイズを画面サイズ(getRealSize):1080×1920と同じにすると、
ステータスバーの下から矩形が描かれ、下側が表示できませんでした。
フルスクリーンにゲームなどを起動すると、ステータスバーが消えるため、矩形も上に詰まる形で
移動するのですが、下側の枠が描かれることはなく、矩形がそのまま上に移動するだけでした。
特定の箇所にマークを付けたいので、四角い枠を画面いっぱいに表現したいのですが、できないものでしょうか?
ご存知の方、ご教示ください。よろしくお願いいたします。
イメージ説明

2018/08/18 02:37追記
ナビゲーションバーに割り込むも半分まで・・・ステータスバーより上にずれて描画されました。
イメージ説明

  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • kakajika

    2018/08/08 17:17

    レイアウトのソース(およびxml)も貼っていただいた方がいいように思います。単にmarginを設定してしまっているとかではないでしょうか?

    キャンセル

  • sunmo

    2018/08/08 17:58

    kakajikaさん、再度ありがとうございます。そしてご指摘ありがとうございます。先ほど少し進展があり、カスタムViewの中で、onMeasureでサイズを指定できることを知り、試したところ、サイズの変更ができました。ただ、ナビゲーションバー、ステータスバーのエリアは表示できませんでした。こちらは可能なのでしょうか?XMLなどはこのあと記載いたします。

    キャンセル

回答 2

checkベストアンサー

+2

前回のご質問 の続きとして回答します。(今回のご質問ではService側のコードが省略されていて他のコードとの繋がりがよくわからないので、省略するならば前回のご質問への参照をちゃんと明示するべきです。)

前回のコードでWindowManager.LayoutParamsを生成している箇所がありましたが、おおむね原因はここにあります。

params = new WindowManager.LayoutParams(
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
             WindowManager.LayoutParams.FLAG_FULLSCREEN |
             WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
        PixelFormat.TRANSLUCENT);
  • オーバーレイ(AnalyzeResultView)のサイズがWindow全体に広がらない件について

↑のLayoutParamsのサイズ指定で WindowManager.LayoutParams.WRAP_CONTENT を使っているのが原因でしょう。 WindowManager.LayoutParams.MATCH_PARENT を使えばWindow全体に広がります。
ただし、Windowのサイズはナビゲーションバーを含めたものにはできないので、それも考慮するとWRAP_CONTENTの方がよさそうです(後述します)。

  • システムバー上への描画について

まず、オーバーレイの描画領域をシステムバー上にまで広げるためには、Windowのレイアウトフラグを指定する必要があります。これはWindowManager.LayoutParamsの生成時に指定可能です。

params = new WindowManager.LayoutParams(
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
             WindowManager.LayoutParams.FLAG_FULLSCREEN |
             WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
             WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR |
             WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS |
             WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
        PixelFormat.TRANSLUCENT);

これでシステムバー上への描画が可能になりますが、Windowのサイズはステータスバーを含めた領域までしか広がりません。なのでナビゲーションバー上への描画も行いたい場合はご質問に書かれていた方法の通りで、 onMeasure 内でgetRealSizeにより取得したサイズを指定してあげる必要があります。(WindowManager.LayoutParamsのheightで直接値を指定してしまう方法もありますが、画面回転も考慮するとWRAP_CONTENTにしておいてonMeasureで計算するのがよさそうです)

まとめると、

  1. WindowManager.LayoutParamsのレイアウトフラグを指定する
  2. onMeasureで画面全体のサイズをViewのサイズに設定する

の2点をやればOKです。

簡単に試してみたスクリーンショットを載せておきます。

スクリーンショット

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/08/18 02:49

    ソースありがとうございます。Kotlinは慣れていなくわからないことだらけなのですが、見る限りでは、OverlayDrawingView とFullscreenOverlayLayout の2つのカスタムViewを追加されていて、FullscreenOverlayLayoutの中にOverlayDrawingView を配置し、FullscreenOverlayLayoutの中でonMeasureされているように見えます。またその時、onMeasureの中では、WindowManagerを使って、サイズを取得し、super.onMeasureにそのサイズをセットしているように見えます。
    同じように記載したつもりなのですが、結果が同じになりました。結果を「試してみたこと」として追加してみました。念のため、ご確認いただけますでしょうか?ソースを見てもらいたいとは思うのですが、gitHubも使用したことがないので、敷居が高く思っています。良い方法があれば教えてください。

    キャンセル

  • 2018/08/18 07:28

    コードについての認識は大体あっていると思います。FullscreenOverlayLayoutが必要な理由は上のコメントに書いています。一応、gistの方にJavaで置き換えたコードも上げておきました。

    追記について:
    実際のコードを見ないことにはなんとも言えませんが、layoutParamsのgravityの設定が抜けてしまっているとかではないでしょうか?Windowの本来の高さよりも大きなものを表示しようとしているわけなので、Gravity.TOPを指定しないと上にずれてしまいます。

    キャンセル

  • 2018/08/18 22:21

    ありがとうございます。できました!Gravity.TOPが必要だったのですね!配置だけと思っていたので、全体の配置に影響しているとは思わず、途中で削除してしまっていました。これでまた一歩進むことができました。

    キャンセル

0

画面サイズ:1080×1920
bitmapサイズ:1080×1794
canvasサイズ:840×1730

横幅は解決できているものとして
縦サイズに注目すると

フィジカルが画面縦サイズ:1920
bitmapサイズ:1794
canvasサイズ:1730
こちらのシミュレーションでは
リンク内容

Pixel2
canvasサイズ + Status bar = bitmapサイズ 
1730 + 64 = 1794

bitmapサイズ + Navigation bar =  画面サイズ
1794 + 126 = 1920

ということでStatus barとNavigation Barの部分が表示されていないと思われます

フルスクリーンで表示にするには
Manifestとstyleで設定するとか
リンク内容

あるいはコードd

@Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus && Build.VERSION.SDK_INT >= 19) {
            hideSystemUI();
        }
    }

    private void hideSystemUI() {
        View decorView = getWindow().getDecorView();
        decorView.setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_IMMERSIVE
                        | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_FULLSCREEN
        );
    }


これを追加すれば可能です。やってみてください
リンク内容

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/08/11 23:43

    ajaさん、コメントありがとうございます。上記の方法(Manifestとソース)、私も見つけて試してみたのですが、現象変わらずでした。せっかく情報提供いただいたのにご期待に沿えず申し訳ありません。
    もしほかにお気づきの点がありましたら、ご指摘ください。よろしくお願いいたします。

    キャンセル

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

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

関連した質問

同じタグがついた質問を見る