web-dev-qa-db-ja.com

アクティビティのライフサイクル-レイアウトが完了したという通知を受け取る

3つのボタンを並べて配置するアクティビティがあります。ボタンのサブクラスを使用して、ボタンのテキストのサイズを変更し、テキストが折り返されないようにしました。 3つのボタンで同じテキストサイズを共有したいと思います。これを行うために、テキストサイズが最小のボタンを検出し、他の2つのボタンをそのテキストサイズに設定する予定です。

私が抱えている問題は、アクティビティのコンポーネントのレイアウトがいつ完了したかを知ることです。これにより、テキストのサイズ変更が行われたことを確実に知ることができます。 Androidドキュメントから、ライフサイクルの最新の通知はonResume()であるように見えますが、レイアウトはこの時点で完了していないようです。通知を受け取る方法はありますか?アクティビティのレイアウトは終了しましたか?

32
kitson

TreeObserversを使用して同様のことを行いました。アタッチするビューを見つけるために少し試してみる必要があるかもしれませんが、ビューが設定されるとこれが発生します。そこから、テキストのサイズを取得し、必要な変更を加えることができます。

mTestButton.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        // make sure it is not called anymore 
        mTestButton.getViewTreeObserver().removeGlobalOnLayoutListener(this);

        float size = mTestButton.getTextSize();
    }
});


編集:
メソッド#removeGlobalOnLayoutListenerは非推奨になりましたが、引き続き有効です。新しい方法と古い方法の両方を使用するには、 このstackoverflowの回答 を参照してください。

28
Greg

私が知っていることから、すべてがロードされていることを通知するイベントや何かはありません。おそらくできることは、oncreateメソッドの最後に、最後のビューの幅が0のときに実行されるAsyncTaskを開始することです。レイアウトが読み込まれると、ビューの実際のサイズは0ではなく、読み込まれたことがわかります。次に、ASyncTaskからのコールバックで、最小のボタンを計算し、フォントサイズを決定できます。

2
matsjoe

Activityライフサイクルコールバックメソッドとそのウィンドウ/レイアウトは本質的にリンクされていません。ただし、Buttonを呼び出した後で操作する限り、setContentViewsが存在することが保証されます。

1
Alex Lockwood

Activity.onWindowFocusChanged(boolean) をオーバーライドして、アクティビティが表示されたときに通知を確実に受信するようにしてください。その後、レイアウトが完了したと見なすことができます。このアプローチで発生する可能性のある問題の1つは、アクティビティがユーザーに表示されるため、ボタンのテキストのサイズが変更されると、サイズの変更がユーザーに一時的に表示されることです。

0
Charles Harley

画像を動的に描画しているので、LinearLayoutでImageViewsのサイズを設定し、それらのサイズを使用したいと思いました。したがって、レイアウトが完了した後に画像を作成する必要があります。

OnCreateの最後にView.post(Runnable)を使用して、Runnableに画像を作成しました。少し実験したところ、レイアウトの前にonStart、onResume、onPostResumeが発生していることがわかりました(ImageViewの幅は0でした)。投稿されたRunnableは、幅が設定されているため、それらすべての後で、レイアウトの後に実行されました。

public void run() {
    // acquire the ImageView
    if (image.getWidth() == 0)
        image.post( this );

    else {
        // create the images, initialize the ImageViews etc.
    }
}

投稿されたRunnableは、おそらく起動手順の後にUIスレッドに投稿されます。 ImageViewsはレイアウトを要求し、要求はRunnableの後に投稿されます。念のため、幅が設定されていることを確認し、設定されていない場合はRunnableを再投稿します。初期化が完了すると、Runnableは再度投稿されません。

0
grimripper

おそらく、ボタン(またはボタンを含むビューグループ)に OnLayoutChangeListener を設定し、そこでフォントのサイズを変更することができますか?レイアウトの変更が有効になる前または後に呼び出されるかどうかはわかりません...

0
QRohlf

ビューのレイアウトがいつ完了したかを知るために、おそらくアクティビティのonCreate()メソッドで実行可能ファイルを指定し、View.onSizeChanged()からこの実行可能ファイルを呼び出します。次のようになります

public void onCreate() {
    view.setLayoutRunnable(new Runnable() {
    @Override
    public void run() {
        //do layout stuff...
    }
});

次に、ビューで次のことを行います。

public Runnable myRunnable;
public void setLayoutRunnable(Runnable runner) {
    myRunnable = runner;
}

@Override
public void onSizeChanged(int w, int h, int oldw, int oldh) {
    if (w > 0 && h > 0 && (w != oldw || h != oldh)) {
        if (myRunnable!= null) 
            myRunnable.run();
    }
}

お役に立てれば。

0
Shafi

Androidは 2ステップ 、測定とレイアウトでレイアウトを行います。ボタンのサイズが必要なだけなので、getWidthの代わりに getMeasuredWidth を使用できます。これは以前に使用可能になるためです。

ボタンの幅を手動で定義するのではなく、LinearLayoutを使用することをお勧めします。特に全幅以外のレイアウトを使用する場合は、Android:weightSumが指定されていることを確認してください。

<LinearLayout 
    ...
    Android:orientation="horizontal"
    Android:weightSum="3"
    >
    <Button 
        ...
        Android:layout_weight="1"
        />
    <Button 
        ...
        Android:layout_weight="1"
        />
    <Button 
        ...
        Android:layout_weight="1"
        />
</LinearLayout>
0
Erik