プログラムでAndroidの画面サイズを取得するにはどうすればよいですか?


132

タッチイベントとビュー測定/レイアウトで使用される単位で、プログラムで画面サイズを確認するにはどうすればよいですか?言い換えれば、私はタッチイベントで使用される座標系では、画面の右下隅の座標をしたい getRawX()/getRawY()View.getLocationOnScreen()

私の携帯電話にはさまざまなモードの「ピクセル」の概念がいくつかあり、それらが一貫したストーリーになっていないため、目的のイベント/ビューユニットを「ピクセル」と呼ぶのをためらっています。

私はこれがstackoverflowや他の場所で多く尋ねられて答えられているのを見ますが、答えはどれも実際に私の携帯電話(droid 4、android 4.1.2)ですべてのモードで機能しません

(ワオ!)

これは、アプリが「画面互換モード」(つまり、マニフェストでtargetSdkVersion <= 10)であるかどうかに関係なく機能する必要があるライブラリコード用であり、位置、サイズについても想定しません。 、またはステータスバーまたはその他の同様の画面装飾の存在。


事実は次のとおりです。

  1. 私の電話(android 4.1.2を実行しているdroid 4)には、540x960の物理ピクセルがあります。

  2. タッチイベントの表示と測定値の表示から求められる単位での画面のサイズは、アプリが画面互換モードの場合は360x640、画面互換モードでない場合は540x960です。これらは私がプログラムで見つける必要のある数値であり、それらを見つけるためにタッチイベントやビューを操作する必要はありませんが、これらの数値を返すAPIを見つけるのは非常に困難です。

  3. さまざまな方法で取得されたDisplayオブジェクトとDisplayMetricsオブジェクトはすべて、画面サイズが540x960 "ピクセル"(画面互換モードかどうかに関係なく)であると主張しています。具体的には、次の例では常に540x960と表示されます:DisplayMetrics。{width、height} Pixels、Display.getSize()、Display.getRealSize()、Display.get {Width、Height}()、

  4. さまざまな方法で取得された構成オブジェクトは、すべてscreen {Width、Height} Dp = 360x614(画面互換モードかどうかに関係なく)と言います。アスペクト比が間違っているので、画面全体を表すとは思いません。(それは画面全体からステータスバーを引いたものだと思います。画面全体が必要です。)画面全体が360x640 dpであると言っても安全ですが、640を返すAPIはわかりません。

  5. さまざまな方法で取得されたDisplayMetricsは、「密度」が画面互換モードの場合は1.0f、画面非互換モードの場合は1.5fであると言います。

  6. アクティビティ getWindow().getAttributes().{width,height} は通常MATCH_PARENT 実際のサイズではなく含まれているため、役に立ちません。しかし、私は明らかにアクティビティから望ましい答えを得ることができます getWindow().getDecorView().getMeasured{Width,Height}() (アクティビティのウィンドウのdecorViewが画面全体を占めているように見えないため、これは実際には意外です。それは、画面からステータスバーを引いたように見えます)。しかし、これに依存したくないのは、ウィンドウのサイズが変更された場合(ソフトキーボードが表示された場合、誰かがwindow.setAttributes()を呼び出した場合、またはアクティビティにまったく参加していない場合)、これが明らかにすべてになるためです。違う。

ピクセル= dp *密度画面互換モードでない場合、報告されたすべての数値(上記の(3)、(4)、(5))と一致するようです:540x960 = 360x640 * 1.5しかし、画面互換性モードでは加算されません:540x960!= 360x640 * 1したがって、何かがおかしいです。

最も簡単な説明は、上記の(3)にリストされているメソッドは、画面互換モードのときに「ピクセル」に対して間違った答えを返すだけだと思います。つまり、360x640の「ピクセル」を返すように意図されていましたが、間違っています代わりに540x960を返します。しかし、それを見る他の方法があるかもしれません。

いずれにせよ、上記のパズルのピースから、モードに関係なく必要な数を取得することは、確かにトリッキーなパズルです。私は両方のモードで私の電話で動作するように見える方法を見つけましたが、それは非常に遠回りであり、それはまだかなり不安定であるように見える2つの仮定に依存しています(以下のコードコメントで説明)。

これが私のレシピです:

/** get screen size in "pixels", i.e. touchevent/view units.
* on my droid 4, this is 360x640 or 540x960
* depending on whether the app is in screen compatibility mode
* (i.e. targetSdkVersion<=10 in the manifest) or not. */
public void getScreenSizePixels(int widthHeightInPixels[/*2*/])
{
    Resources resources = getResources();
    Configuration config = resources.getConfiguration();
    DisplayMetrics dm = resources.getDisplayMetrics();
    // Note, screenHeightDp isn't reliable
    // (it seems to be too small by the height of the status bar),
    // but we assume screenWidthDp is reliable.
    // Note also, dm.widthPixels,dm.heightPixels aren't reliably pixels
    // (they get confused when in screen compatibility mode, it seems),
    // but we assume their ratio is correct.
    double screenWidthInPixels = (double)config.screenWidthDp * dm.density;
    double screenHeightInPixels = screenWidthInPixels * dm.heightPixels / dm.widthPixels;
    widthHeightInPixels[0] = (int)(screenWidthInPixels + .5);
    widthHeightInPixels[1] = (int)(screenHeightInPixels + .5);
}

画面のサイズを見つけるためのより良い/よりきれいな方法はありますか?


29
+1すばらしい質問であり、多くの研究努力を示しています。
Alex Gittemeier 2013

1
@Don docsで、互換モードは古いセットアップで「ズームして合わせる」操作を停止することが説明されています。ただし、「動作のしくみ」については明確に説明されていません。観察から、密度のスケーリングをオフにするだけだと思います。つまり、1pxは1dpになります。この変更はレンダリング部分のみにありDisplayMetrics、そのような変更が更新されることはありません。このような問題はすでに提出されています。
SD

@ user117-面白い。上手一部 DisplayMetricsのは、1.0に変更least--密度で更新されました。しかし、widthPixels / heightPixelsは一致するように変更されなかったようです。引用された問題に関しては、動作が3.1の動作に戻ったように見えます(つまり、heightPixels ステータスバーが含まれているのがわかります...しかし、間違った単位で表示されているようです)
Don Hatch

@DonHatchありがとう、親切に-私は実際にはStackExchangeで不思議なほどに思慮深い種類の思慮深い質問に賞賛を与えようとしていました-「本当の」以上の質問が答えに何もないことに注意してください(低い)トピックに関する聴衆の知識の質。今、自分の質問が次々に「本物ではない」という理由で締め切られることにトラウマを感じるかもしれません、そしてユーモアのセンスが私を失敗させているかもしれませんが、それは「素敵な」レシピエントの回答が本当にある質問のように見え始めますここでこれがどうなるか...そしてもちろん、私はあなたのものを支持しました:)
mlvljr 2013

ところで!ここに私の疑惑の線に沿ったものがあります:michael.richter.name/blogs/…(特に彼の(1)のポイント、迅速に作成された回答に関する1つを参照してください-実際にはこのQのケースだけです!)。とにかく、ハッピーNY(鉱山は11分で到着します)!:)
mlvljr 2013

回答:


41
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;

すべてのボタン、テキストビューなどがこの単位で測定されるため、画面サイズをピクセル単位で測定できます。これはセンチメートルよりも良い測定単位です。私が通常使うもの


3
Op(特にポイント3)によると、これは画面互換モードでは正しくないのではないでしょうか。
トム

9

DisplayMetricsを使用すると、任意のデバイスの画面の高さと幅を取得できます。幅と高さは回転の影響を受けやすいことに注意してください。これがコードです。

DisplayMetrics metrics; 
int width = 0, height = 0;

onCreateメソッド内

 metrics = new DisplayMetrics();        
 getWindowManager().getDefaultDisplay().getMetrics(metrics);

 height = Math.min(metrics.widthPixels, metrics.heightPixels); //height
 width = Math.max(metrics.widthPixels, metrics.heightPixels); //width

これを試して。


2
いいえ、(3)で述べたように、metrics。{width、height} Pixelsは、画面互換性モードでは正しい答えを与えません
ドンハッチ2013

また、私は発見しました:画面が回転した場合、またはその逆の場合、lite metrics.heightPixelsが幅を与える可能性があるようです!
JohnyTex

8

あなたの#6では、DecorViewがあなたが望むものを提供しているように見えますが、それは実現可能だとは思いません。私はそれがあなたが来ることができるのと同じくらい近いと信じています。のドキュメントによるとWindow.getDecorView

トップレベルのウィンドウ装飾ビュー(標準のウィンドウフレーム/装飾とその中のクライアントのコンテンツを含む)を取得します。これは、ウィンドウマネージャーにウィンドウとして追加できます。

ステータスバーはそこで言及されているウィンドウ装飾の一部です。ソフトウェアキーボードやその他のオーバーレイは独自のウィンドウを受け取るため、関連する値に干渉しないでください。これは正確には表示メトリックではありませんが、アプリケーションがフルスクリーンの場合、互換性トランスレータでフィルタリングされたフルスクリーンサイズである必要があります。他のアプリケーションはあなたのアプリケーションにアクセスできませんWindowため、他のアプリケーションが見ていなくても属性を変更することを心配する必要はありません。

お役に立てば幸いです。


5

私はこれをコメントとして入れるべきですが、そのための担当者がいません。
これは完全に正しい答えではない可能性がありますが、DisplayMetricsメソッドで高さと幅を切り替えたときに寸法が表示されました。

    DisplayMetrics metrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(metrics);   
    width = metrics.heightPixels;
    height = metrics.widthPixels;

これは正しくないかもしれませんが、理由はわかりませんが、うまくいきました。


これは、画面が回転したためだと思います。
JohnyTex

それは私を信用していませんでした。
abhyudayasrinet


3

私はピタゴラスの定理を使用してAndroidフォン/タブレット画面の対角サイズを見つけましたが、同じ原理をiPhoneまたはBlackberry画面に適用できます。

DisplayMetrics met = new DisplayMetrics();                
this.getWindowManager().getDefaultDisplay().getMetrics(met);// get display metrics object
String strSize = 
new DecimalFormat("##.##").format(Math.sqrt(((met.widthPixels / met.xdpi) *
(met.widthPixels / met.xdpi)) +
((met.heightPixels / met.ydpi) * (met.heightPixels / met.ydpi))));
// using Dots per inches with width and height

ピタゴラスは天才だったに違いない、彼は何年も前にスマートフォンのプログラミングを知っていた:p


1

以下のメソッドを使用して、デバイスの幅を取得します。

public static int getDeviceWidth(Context context){
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    int width=display.getWidth();
    return width;
}

このメソッドは非推奨です。displaymetricsメソッドを使用してください。
Simon

0

この機能は、Android画面サイズの幅と高さを簡単に取得するのに役立つと思います。以下に示すように、関数は幅と高さを整数の配列として返します

private int[] getScreenSIze(){
        DisplayMetrics displaymetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        int h = displaymetrics.heightPixels;
        int w = displaymetrics.widthPixels;

        int[] size={w,h};
        return size;

    }

そして、あなたのcreateメソッドでは、以下に示すように幅と高さを出力します

 int[] screenSize= getScreenSIze();
        int width=screenSize[0];
        int height=screenSize[1];
        screenSizes.setText("Phone Screen sizes \n\n  width = "+width+" \n Height = "+height);

ソースコードダウンロードしてAndroidスタジオでテストする


0

これは私にとってはうまくいきます:

int width = Resources.getSystem()。getDisplayMetrics()。widthPixels;

int height = Resources.getSystem()。getDisplayMetrics()。heightPixels;

これを使用して、横方向のリサイクル業者ビューでアイテムの幅を更新しました。


-1

Kotlinのこのソリューションについては、これを試してください:

private fun yourFunction(){
   val metrics = DisplayMetrics()
   windowManager.defaultDisplay.getMetrics(metrics)
   val width = metrics.widthPixels
   val height = metrics.heightPixels
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.