Androidのつまづき「DialogFragmentの横幅が反映されない」
発端
今回はDialogFragmentの横幅がlayout.xmlで指定しても変わらないので、なんでだろ~と思って調べてみました。
参考サイト↓
Y.A.M の 雑記帳: Android DialogFragment では Dialog のサイズ指定は onActivityCreated でやれ
画面の解像度やdensity(ピクセル密度)の取得方法 | Android Techfirm Lab
今回は上の二つのサイトを参考にさせていただきました。
問題のコード
layout.xmlは
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="300dp" android:layout_height="wrap_content" android:layout_margin="10dp" android:orientation="vertical"> <!-- ここにその他のViewを配置 --> </LinearLayout>
というような感じで、rootViewにwidthを指定しているものの表示されるのが300dpよりも全然小さい。。。
なぜかなぁと思って調べていたら出てきたのがこちらの記事。
Y.A.M の 雑記帳: Android DialogFragment では Dialog のサイズ指定は onActivityCreated でやれ
こちらによると、どうやらsetContentView内でLayoutParamsにWRAP_CONTENTを内部的に設定しているらしい。
そして丁寧にその対処法も書いてくれていて大助かり。対処としては、
@Override public void onActivityCreated(Bundle savedInstanceState){ super.onActivityCreated(savedInstanceState); Dialog dialog = getDialog(); /* LayoutParamsを取得する */ WindowManager.LayoutParams layoutParams = dialog.getWindow().getAttributes(); /* DisplayMetrics を用いてDisplay上の大きさ(?)を取得し、layoutParamsに設定する処理(省略) */ /* LayoutParamsをセット */ dialog.getWindow().setAttributes(layoutParams) }
というような感じのようです。
んでもって、ここだけの情報だとPixelでの指定方法が書かれているだけだったので、併せてdpでの指定に関する記事を探したところ
画面の解像度やdensity(ピクセル密度)の取得方法 | Android Techfirm Lab
こちらの記事を見つけました。
どうやらAndroidの中での「dp」の倍率は以下のコードで取得できるようです。
DisplayMetrics metrics = new DisplayMetrics(); context.getWindowManager().getDefaultDisplay().getMetrics(metrics); /* metrics.scaledDensity でとれるのがdpの倍率*/
取得できるのは倍率なので、これをきちんと大きさに変換してやる必要があります。
(具体的には、「設定したい大きさ * metrics.scaledDensity」で変換する。注意点としては型はfloatであること。)
これらを踏まえて修正したコードがこちら
修正後のコード
↓ layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" android:orientation="vertical"> <TextView android:id="@+id/title" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:gravity="center" android:text="posting" android:textSize="20sp" /> <EditText android:id="@+id/editText" android:layout_margin="10dp" android:layout_width="match_parent" android:layout_height="90dp" android:hint="describe contents"/> <Button android:id="@+id/postBtn" android:layout_width="wrap_content" android:layout_height="40dp" android:layout_margin="10dp" android:text="send" android:textSize="20sp"/> </LinearLayout>
↓ myDialogFragment
import android.app.Dialog; import android.content.Context; import android.media.Image; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.DialogFragment; import android.support.v4.app.Fragment; import android.util.DisplayMetrics; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import my.com.myAppName.R; public class myDialogFragment extends DialogFragment { public myDialogFragment() { // Required empty public constructor } private EditText editText; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } /** * LayoutParamsを操作し、横幅を適用 */ @Override public void onActivityCreated(Bundle savedInstanceState){ super.onActivityCreated(savedInstanceState); Dialog dialog = getDialog(); //AttributeからLayoutParamsを求める WindowManager.LayoutParams layoutParams = dialog.getWindow().getAttributes(); //display metricsでdpのもと(?)を作る DisplayMetrics metrics = new DisplayMetrics(); getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics); //LayoutParamsにdpを計算して適用(今回は横幅300dp)(※metrics.scaledDensityの返り値はfloat) float dialogWidth = 300 * metrics.scaledDensity; layoutParams.width = (int)dialogWidth; //LayoutParamsをセットする dialog.getWindow().setAttributes(layoutParams); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View view = inflater.inflate(R.layout.layout, container, false); postText = (EditText)view.findViewById(R.id.editText); Button postBtn = (Button)view.findViewById(R.id.postBtn); postBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(getActivity(),editText.getText(),Toast.LENGTH_SHORT).show(); dismiss(); } }); return view; } @Override public Dialog onCreateDialog(Bundle savedInstanceState){ Dialog dialog = new Dialog(getActivity()); //TITLE部分のないdialogの生成 dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE); dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); return dialog; } }
今回はこんなもんで、終わります。