19
17

More than 5 years have passed since last update.

Android レイアウトXMLで指定したViewの幅・高さの取得

Last updated at Posted at 2015-10-12

Activityの場合

従来のActivityベースのアプリの場合、『onWindowFocusChanged()』で取得すればよいです。

MainActivity.java
public class MainActivity extends AppCompatActivity {

    private LinearLayout topContainer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        topContainer = (LinearLayout) findViewById(R.id.top_container);
        // Width = 0, Height = 0
        Log.i("", "MainActivity#onCreate() " +
                "Width = " + String.valueOf(topContainer.getWidth()) + ", " +
                "Height = " + String.valueOf(topContainer.getHeight()));

    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        // Width = 1440, Height = 525
        Log.i("", "MainActivity#onWindowFocusChanged() " +
                "Width = " + String.valueOf(topContainer.getWidth()) + ", " + 
                "Height = " + String.valueOf(topContainer.getHeight()));
    }
}

Fragmentの場合

方法1 独自のインターフェースで実装する

  • how to get the onWindowFocusChanged on Fragment?
  • 独自のインターフェースを定義して、ActivityでonWindowFocusChanged()が呼ばれた際に、Fragmentにも通知する。
  • FragmentとActivityの結びつきが強くなってしまう可能性がある。

方法2 OnGlobalLayoutListener#onGlobalLayout()を利用する

  • onGlobalLayout()でレイアウトに変化があった場合に値を取得します。
  • OnGlobalLayoutListenerは、レイアウトが変化する度に呼ばれるので、再取得が不要な場合には、リスナーを削除しておきます。
MainActivityFragment.java

public class MainActivityFragment extends Fragment {

    public MainActivityFragment() {
    }

    private LinearLayout topContainer;
    private ViewTreeObserver.OnGlobalLayoutListener globalLayoutListener;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_main, container, false);
        topContainer = (LinearLayout) view.findViewById(R.id.top_container);

        // Width = 0, Height = 0
        Log.i("", "MainActivityFragment#onCreateView() " +
                "Width = " + String.valueOf(topContainer.getWidth()) + ", " +
                "Height = " + String.valueOf(topContainer.getHeight()));

        globalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                // Width = 1440, Height = 525
                Log.i("", "OnGlobalLayoutListener#onGlobalLayout() " +
                        "Width = " + String.valueOf(topContainer.getWidth()) + ", " +
                        "Height = " + String.valueOf(topContainer.getHeight()));

                // removeOnGlobalLayoutListener()の削除
                topContainer.getViewTreeObserver().removeOnGlobalLayoutListener(globalLayoutListener);
            }
        };
        topContainer.getViewTreeObserver().addOnGlobalLayoutListener(globalLayoutListener);

        return view;
    }
}

その他

  • いずれの場合でも、幅・高さが取得できるのは、レンダリング後(画面への表示が終わった後)です。
    • 基本的に、相対表示なので、一度画面に表示してからでないと、絶対値が取れないということでしょう。
  • Android 5.1(API 22)で確認しました。
    • removeOnGlobalLayoutListener()の実装方法は、Android 4.0(API 16)以上と未満で異なります。
19
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
17