活动生命周期-接收布局已完成的通知



我有一个活动,其中有3个按钮并排放置。我使用了Button的一个子类,它将调整按钮文本的大小,以防止文本换行。我希望这3个按钮共享相同的文本大小。为了做到这一点,我打算检测具有最小文本大小的按钮,并将其他2个按钮设置为该文本大小。

我遇到的问题是知道"活动"何时完成组件布局,这样我就可以可靠地知道文本的大小调整已经发生。从Android文档中可以看出,生命周期中的最新通知是onResume(),但此时布局似乎尚未完成。是否有接收"活动"布局已完成通知的方法?

我使用Tree Observer做过类似的事情。你可能需要玩一玩,才能找到它应该附加的视图,但一旦设置了视图,它就会启动。从那里,您可以获得文本的大小,并进行任何需要的更改。

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();
}
});


EDIT:
方法#removeGlobalOnLayoutListener已被弃用,但仍然有效。要同时使用新方法和旧方法,请参阅此stackoverflow答案。

据我所知,没有事件或东西告诉您所有内容都已加载。您可以做的是在oncreate方法结束时启动一个AsyncTask,该任务在上一个视图的宽度为0时运行。加载布局时,视图的实际大小将为0,这样您就知道它已加载。在ASyncTask的回调中,您可以计算最小的按钮并确定字体大小。

Activity生命周期回调方法及其窗口/布局没有内在链接。但是,只要在调用setContentView之后对其进行操作,就可以保证Button存在。

也许您可以在按钮(或包含按钮的视图组)上设置一个OnLayoutChangeListener,并在那里重新调整字体大小?我不确定这是在布局更改生效之前还是之后调用的。。。

您可以尝试重写Activity.onWindowFocusChanged(布尔值),以便在活动可见时可靠地接收通知。然后,您可以假设布局已经完成。这种方法可能存在的一个问题是"活动"对用户可见,因此,如果调整按钮文本的大小,则用户将短暂地看到大小的变化。

Android将分两步进行布局,即测量和布局。因为您只想要按钮的大小,所以可以使用getMeasuredWidth而不是getWidth,因为这将在早期提供。

我建议您使用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>

为了知道视图的布局何时完成,也许我会在活动的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();
}
}

希望这能有所帮助。

我正在动态绘制图像,希望通过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就不会再次发布。

当我尝试制作水平堆叠的按钮时,我只给它们wrap_parent的layout_width,但给它们1的layout_weight。

通过这种方式,它们都试图占据尽可能多的可用空间,这些空间由父布局均匀分布。

示例代码应该是这样的,我希望它能有所帮助:

<LinearLayout 
android:id="@+id/buttons"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<Button 
android:id="@+id/okButton"
android:layout_height="wrap_content" 
android:layout_width="wrap_content"
android:text="OK"
android:layout_weight="1"
/>
<Button 
android:id="@+id/cancelButton"
android:layout_height="wrap_content"
android:layout_width="wrap_content" 
android:text="Cancel"
android:layout_weight="1"
/>
</LinearLayout>

-serkan

您可以使用iswindow()。覆盖它。它将在onPause()之前被调用。

根据"活动生命周期",当调用onResume()时,布局被视为完成。这是向用户显示屏幕的时候。所以你可以盲目地使用这个功能中的按钮。

最新更新