fc2ブログ

戌印-INUJIRUSHI- (Androidあれこれ)

Androidのプログラミングをメインにしてます。記事に貼られたソースコードはダブルクリックすることで行番号をはずしてコピーすることができます。

 
1
2
3
4
5
6
7
8
9
11
12
13
14
15
16
17
18
19
20
21
22
24
25
26
27
28
02

デバイスのDPIを取得 と dip ⇔ px の変換

Android ではデバイス毎に画面サイズと解像度が異なるため、デザインする際のサイズ指定に困ります。

そこでレイアウトのサイズ指定では dip/dp を使ってサイズ指定を行います。

dip (Density Independent Pixel) とは、解像度に応じてサイズを変える単位です。
この dip を指定することで画面上のサイズを統一することができます。
※ dip = dp で、ここでは文字数の少ない dp を使います。

さて、この dip が何 px なのかを計算するには解像度を知る必要があります。
解像度は DIP (Dots Per Inch) と呼ばれ、1インチ幅のドット数を表します。

【Android の解像度 (2/13/02/23 時点)】
ldpi : 120 dpi
mdpi : 160 dpi
hdpi : 240 dpi
xhdpi : 320 dpi
xxhdpi : 480 dpi
txdpi : 213 dpi (Nexus 7)

dpi は mdpi (160 dpi) を基準とし、mdpi のとき 1dp = 1px となります。
mdpi を 1 と考えたときの比率は以下のようになります。
ldpi : mdpi : hdpi : xdhpi : xxhdpi : tvdpi = 0.75 : 1 : 1.5 : 2 : 3 : 1.33125

詳しい内容については、こちらのサイトがオススメです。
pucchon design - Androidのdip(dp)ってpxに換算すると何なのさ!-めんどくさいのでDip Calc作りました-


以上、前置き。
以下はタイトルどおりの取得と計算について。

解像度 (DPI) は DisplayMetrics#densityDpi から取得することができます。
取得する方法は2通り。
// WindowManager から取得する (要 Activity)
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int dpi1 = metrics.densityDpi;

// リソースから取得する (要 Context)
int dpi2 = getResources().getDisplayMetrics().densityDpi;
※以降は取得する手順の少ない後者を使います。

変換に使う解像度との比率を計算します。
// DPI を取得する
int dpi = getResources().getDisplayMetrics().densityDpi;

// dpi を元に比率を計算する ( dpi ÷ 基準値(mdpi) )
float density = dpi / 160f;


と…
わざわざ前置きに計算式まで書きましたが、DPIを取得して計算しなくても直接比率を取得することができます
【参考】Y.A.M の 雑記帳 - Android dip, dp, から pt, px に変換する

DisplayMetrics#density から比率を取得する。
float density = getResources().getDisplayMetrics().density;

dp を pixel に変換するには前述の比率をかけます。
次の例では 50dp を pixel に変換させます。
// density (比率)を取得する
float density = getResources().getDisplayMetrics().density;

// 50 dp を pixel に変換する ( dp × density + 0.5f(四捨五入) )
int px = (int) (50f * density + 0.5f);

pixel から dp に変換するには比率で割ります。
次の例では 50px を dp に変換させます。
// density (比率)を取得する
float density = getResources().getDisplayMetrics().density;

// 50 px を dp に変換する ( pixel ÷ density + 0.5f(四捨五入) )
int dp = (int) (50f / density + 0.5f);


2013/03/02 内容が間違っていたため修正しました。
1週間放置状態だったので情報鵜呑みにして間違えてしまった方いたらすみません m(_ _)m
スポンサーサイト



子Viewが親の状態を共有:android:duplicateParentState

Android では android:duplicateParentState を使うことにより、子 View が親の状態を共有することができます。
※ 状態 = クリック、選択、有効/無効など (android:visibility は対象外)

親の状態を共有すると親が優先されるため、子 View 側の状態は無視されます。

【参考】Y.A.M の 雑記帳 - Android android:duplicateParentState

android:duplicateParentState=[true | false] はレイアウトXMLでの定義方法で、
Java側では View#setDuplicateParentStateEnabled(boolean enabled) を使います。

android:duplicateParentState="true" の効果
・親の状態変化を子が共有する
 ⇒ 親がクリックされると、子もクリックされた状態として表示される。
・子の状態は反映されない
 ⇒ 子が無効になっていても、親が有効であれば有効として表示される。
イベントは共有されない
 ⇒ 子に onClick を設定した場合、親がクリックされても子の onClick は実行されない。
  子がクリックされると onClick が実行される。
共有されるのは見た目だけ
 ⇒ 親を無効にしていても、子が有効であれば子の onClick は実行される。

■ イメージ
Android_duplicateParentState.png

■ レイアウトXML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<LinearLayout
android:id="@+id/layout1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#ffcccc"
android:gravity="center" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="android:duplicateParentState=false(default)"
android:textSize="20sp"
android:textStyle="bold" />
</LinearLayout>

<LinearLayout
android:id="@+id/layout2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#ccccff"
android:gravity="center" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:duplicateParentState="true"
android:text="android:duplicateParentState=true"
android:textSize="20sp"
android:textStyle="bold" />
</LinearLayout>

<LinearLayout
android:id="@+id/layout3"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#ccffcc"
android:gravity="center" >
<TextView
android:id="@+id/text3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:duplicateParentState="true"
android:text="android:duplicateParentState=true\nLinearLayout:Enabled=true\nTextView:Enabled=false"
android:textSize="20sp"
android:textStyle="bold" />
</LinearLayout>

</LinearLayout>

■ TestLayoutActivity.java
package jp.inujirushi.android.sample;

import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.TextView;

public class TestLayoutActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle("android:duplicateParentState");
setContentView(R.layout.activity_layout);

// android:duplicateParentState="false"(default)
LinearLayout l1 = (LinearLayout) findViewById(R.id.layout1);
l1.setEnabled(false);

// android:duplicateParentState="true"
LinearLayout l2 = (LinearLayout) findViewById(R.id.layout2);
l2.setEnabled(false);

// android:duplicateParentState="true"
// LinearLayout:Enabled=true
// TextView:Enabled=false
TextView text3 = (TextView) findViewById(R.id.text3);
text3.setEnabled(false);

// Java 側で親の状態を参照する場合
// text3.setDuplicateParentStateEnabled(true);
}
}

コレはどういうときに使うのかというと…

例えば、ImageView (以下、子)をクリックするとイベントが発生するとします。
この子はクリックしたことを知らせるためにクリック中は画像が変わるようになっています。

しかし、子は小さすぎてクリックし辛いため LinearLayout 等の ViewGroup(以下、親)の中に入れ、親側に onClick イベントを設定します。

このままだと、親がクリックされても子の画像は変わりません。

そこで 子に android:duplicateParentState="true" を設定します。
すると親がクリックされたときに、子も同様にクリックされたとみなされ子がクリック中の画像に変わります。


と、レイアウトを設定する際のテクニックでした。
ただ、前述の『android:duplicateParentState="true" の効果』に書いたように共有されるのは見た目だけなので注意してください。
プロフィール

とむ・やむくん

Author:とむ・やむくん
管理人について

Windows 7 / 64bit
Eclipse 4.2 Juno (日本語パッチ済)

スポンサーサイト
最新トラックバック
検索フォーム
ブロとも申請フォーム
QRコード
QR
Twitter
2013/01/04 19:00 カウント開始