【Kotlin/Android Studio】画面(スクリーン)の横幅を取得する方法!デバイスサイズ
この記事からわかること
- Android Studio/Kotlinで画面(スクリーン)のサイズを取得するには?
- デバイスサイズを識別する
- 横幅や縦幅
- APIによるコードの違い
- pxやdpiでの取得
- SizeやResolution、Densityとは?
- DisplayMetricsクラスとWindowMetricsクラスの使い方
- getSystemServiceメソッド:WINDOW_SERVICEとWindowManager
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
環境
- Android Studio:Flamingo
- Kotlin:1.8.20
Androidの画面サイズ情報
AndroidやiOSなどのモバイル端末のディスプレイにはサイズを表す単位や言葉(ピクセルやdpi、解像度など)が多く存在します。使用する端末によってサイズや解像度は大きく異なるので小さい端末でUIが大きく崩れてしまうなんてことはよくあります。これを起こさないためにそれぞれの違いをまずははっきりさせておきます。
AndroidではAndroid Studioのエミュレーターを管理しているDevice Managerから機種を追加しようとした際に機種やサイズなどの一覧を確認できます。ここでは「Size」、「Resolution」、「Density」の3つの値が確認できます。
それぞれが表しているのは以下の通りです。詳しくは後述していきます。
- Size:画面のインチ
- Resolution:解像度(横ピクセル × 縦ピクセル)
- Density:ピクセル密度
インチ:inch
インチとは日本で言うところのセンチメートルやミリメートルなどといった長さを表す指標のことです。「1インチ = 2.54cm」と決められています。
Androidデバイスで「6.0インチ」などと謳われているのはディスプレイの対角線の長さのことです。
ピクセル:pixel
ピクセルとは日本語で言うところの「画素」のことで、デジタル画面や画像などを表示する際の最小表示単位です。ピクセルは色のついた点のようなものでその点がたくさん集まって画面を表示しています。もちろん数が多いほどより綺麗に繊細に色味を表現できることになります。
AndroidではResolution(解像度)として「横方向のピクセル × 縦方向のピクセル」形式で表現されています。
ピクセル密度:Density
Density(デンシティ)とはピクセル密度のことです。ピクセル密度とはディスプレイ上の1インチあたりのピクセル数を示す指標であり、ピクセル密度が高いほど画面がより鮮明になります。
ピクセル密度は「dots per inch(dpi)」(1インチあたりにいくつピクセル(ドット)があるかを示す指標)という単位で表現されることがあります。ピクセル密度は物理サイズ(インチ)とディスプレイの解像度(横方向と縦方向のピクセル数)に基づいて計算可能です。
dpiとppiの違い
ピクセルに関連した解像度を表す言葉に「pixels per inch(ppi)」という単位もあります。ppiとの違いは使用される機械から見た場合の呼び方の違いであり、「1インチあたりにいくつピクセル(ドット)があるかを示す指標」と言う意味合いでは同義になります。
- dpi:dots per inch :主にプリンタなどに使用
- ppi:pixels per inch:主にディスプレイなどに使用
Androidではピクセル密度をdpiを使って表現しているようです。ちなみにAndroidアプリ開発ではピクセルでの指定はできるだけ非推奨となっています。これは同じピクセルサイズ(解像度)のデバイスがあってもピクセル密度が異なる場合、ディスプレイ表示に差が生まれてしまうからです。
また画像を格納する際もピクセル密度を意識する必要があります。
Androidでコードから取得できるデバイス情報
Androidではコードからアプリを実行しているデバイスの画面サイズなどの情報を取得することが可能になっています。API30以降からWindowMetrics
クラスというのが追加されたのでAPI30以降と以前ではAPIレベルによってコードが少し異なります。
使用するクラス
- API30 以上:WindowMetricsクラス
- API29 以下:DisplayMetricsクラス
また今回はデモとして「Pixel 3a」の情報(以下)を取得していきます。
- Size: 5.6
- Resolution:1080px × 2220px
- Density:440dpi
API30以上:WindowMetricsクラス
API30以上でコードからデバイスの画面情報を取得するにはWindowMetrics
クラスを使用します。WindowMetricsクラス
はgetSystemService
メソッドの引数にWINDOW_SERVICE
を渡してWindowManager
クラスを取得し、取得したWindowManager
からcurrentWindowMetrics
(getCurrentWindowMetrics)を使用して取得します。
val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
val windowMetrics = windowManager.currentWindowMetrics
解像度を取得する
解像度を取得したい場合はまずWindowMetrics
クラスのbounds
(getBounds)を取得します。boundsは日本語で「境界」の意味です。
取得したbounds
のwidth
メソッドとheight
メソッドからデバイスのpx単位の大きさを取得できます。
val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
val windowMetrics = windowManager.currentWindowMetrics
val bounds = windowMetrics.bounds
var screenWidth = bounds.width()
val screenHeight = bounds.height()
print(screenWidth.toString()) // 1080
print(screenHeight.toString()) // 2220
ピクセル密度:Density(dpi)を取得する
ピクセル密度:Densityを取得するためにはまずresources.displayMetrics.density
から論理密度を取得します。これはt密度独立ピクセル単位のスケーリング係数として計算された値であり、160dpiの画面で密度値が1になります。今回は440dpiなので440 / 160 = 2.75
となります。
val density = resources.displayMetrics.density
print(density) // 2.75
dpiで取得するには取得した論理密度をデバイスの大きさから割ればdpiでの大きさを取得できます。
val bounds = windowManager.currentWindowMetrics.bounds
val density = resources.displayMetrics.density
var screenWidthDpi = bounds.width()/density
var screenHeightDpi = bounds.Height()/density
print(screenWidthDpi.toString()) // 392.72726
print(screenHeightDpi.toString()) // 807.2727
API29以下:DisplayMetrics
API29以下ではAPI1から追加されているDisplayMetrics
クラスのみを使用します。
DisplayMetrics
クラスのみでデバイスの画面サイズを取得するにはgetSystemService
メソッドの引数にWINDOW_SERVICE
を渡してWindowManager
クラスを取得する流れは変わりません。次にDisplayMetrics
をインスタンス化してwindowManager
にgetMetrics
メソッドを使用してセットします。
val windowManager = this.getSystemService(Context.WINDOW_SERVICE) as WindowManager
val displayMetrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(displayMetrics) // ちなみにここが非推奨になっている?
val screenWidth = displayMetrics.widthPixels
val screenHeight = displayMetrics.heightPixels
print(screenWidth.toString()) // 1080
print(screenHeight.toString()) // 2154
あとはwidthPixels
とheightPixels
メソッドからデバイスのpx単位の大きさを取得できます。高さのみ微妙に誤差が生じていました。
ピクセル密度:Density(dpi)を取得する
ピクセル密度:Density(dpi)を取得するのは簡単でxdpi
プロパティまたはydpi
プロパティを使用します。やはり先ほどと少し誤差が生まれる(こちらのが端数のない数値?)ようです。
screenWidthDpi = displayMetrics.xdpi
screenHeightDpi = displayMetrics.ydpi
print(screenWidthDpi.toString()) // 440
print(screenHeightDpi.toString()) // 440
WindowManager
WindowManagerクラスはウィンドウ(画面上の表示領域)の管理と操作を担当するシステムサービスです。
おまけ:APIでコードを分岐させる
今まではActivityに記述するコードでしたがFragment用のコードも載せておきます。といっても違いはContext
の取得方法だけですが。またついでにAPIレベルを識別してコードを分岐させるようにsてあります。
おすすめ記事:【Kotlin/Android Studio】コードからAPI(OS)レベルを取得して分岐する方法!Build.VERSION.SDK_INT
val context:Context = requireContext()
val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
var screenWidth = 0f
// Android10 (29) と Android11以降 (30)で分岐
if(Build.VERSION.SDK_INT <= 29){
val displayMetrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(displayMetrics)
screenWidth = displayMetrics.widthPixels
}else if(Build.VERSION.SDK_INT >= 30){
val bounds = windowManager.currentWindowMetrics.bounds
screenWidth = bounds.width
}
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。