- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我注意到在处理来自 Activity 的配置更改时,onLayout 和 onSizeChanged 在方向更改后立即连续调用 两次,从横向->纵向或从纵向->横向.此外,第一个 onLayout/onSizeChanged 包含旧尺寸(旋转之前),而第二个 onLayout/onSizeChanged 包含新(正确)尺寸。
有谁知道为什么,和/或如何解决这个问题?似乎屏幕尺寸的变化可能在配置更改后的相当长一段时间内发生 - 即,当 onConfigurationChanged
被调用时,尺寸在配置更改后立即不正确?
下面是代码的调试输出,显示了从纵向到横向旋转后的 onLayout/onSizeChanged 调用(请注意,设备是 540x960,因此横向宽度应为 960,而纵向宽度应为 540):
03-13 17:36:21.140: DEBUG/RotateTest(27765): onConfigurationChanged: LANDSCAPE
03-13 17:36:21.169: DEBUG/RotateTest(27765): onSizeChanged:540,884,0,0
03-13 17:36:21.189: DEBUG/RotateTest(27765): onLayout:true-0,0,540,884
03-13 17:36:21.239: DEBUG/RotateTest(27765): onSizeChanged:960,464,540,884
03-13 17:36:21.259: DEBUG/RotateTest(27765): onLayout:true-0,0,960,464
另请注意,第一个 onSizeChanged 的 oldwidth 和 oldheight 为 0,表示我们刚刚添加到 View 层次结构中 - 但横向尺寸错误!
下面是说明此行为的代码:
package com.example;
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import android.widget.FrameLayout;
public class MyActivity extends Activity
{
private static String TAG = "RotateTest";
@Override
public void onConfigurationChanged(Configuration newConfig) {
Log.d(TAG, "onConfigurationChanged: " + (newConfig.orientation == 1 ? "PORTRAIT" : "LANDSCAPE"));
super.onConfigurationChanged(newConfig);
_setView();
}
@Override
public void onCreate(Bundle savedInstanceState)
{
Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
_setView();
}
private void _setView() {
MyHorizontalScrollView scrollView = new MyHorizontalScrollView(this, null);
setContentView(scrollView);
}
}
package com.example;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.HorizontalScrollView;
public class MyHorizontalScrollView extends HorizontalScrollView {
private static String TAG = "RotateTest";
public MyHorizontalScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
Log.d(TAG, "onLayout:" + String.format("%s-%d,%d,%d,%d", changed, l, t, r, b));
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
Log.d(TAG, "onSizeChanged:" + String.format("%d,%d,%d,%d", w, h, oldw, oldh));
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example"
android:versionCode="1"
android:versionName="1.0"
>
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="9"/>
<application android:label="@string/app_name"
>
<activity android:name="MyActivity"
android:label="@string/app_name"
android:configChanges="orientation"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
最佳答案
很长一段时间以来,我自己一直在想这个问题。
我回答这个问题的方式——因为我相信答案是,这取决于——是在 requestLayout
中添加一个 try/catch
或 logging 语句方法。这使您可以查看何时提出重新测量和重新布局的请求,如果是 try/catch
,由谁提出。
Android 中的布局方式是使用 requestLayout
将 View 标记为脏布局。始终在某个时间间隔内在 UI 线程上运行的 Android 循环程序将在未来某个不确定的时间点重新测量和重新布局树中已标记为脏的 View 。
我冒昧地猜测 onConfigurationChanged
,您会收到多个 requestLayout
调用,而循环程序会在它们中间的某个地方调用 onMeasure
。
这就是我的日志记录:
11-07 15:39:13.624: W/YARIAN(30006): requestLayout
11-07 15:39:13.632: W/YARIAN(30006): requestLayout
11-07 15:39:13.640: W/YARIAN(30006): requestLayout
11-07 15:39:13.647: W/YARIAN(30006): requestLayout
11-07 15:39:13.686: W/YARIAN(30006): requestLayout
11-07 15:39:13.718: W/YARIAN(30006): requestLayout
11-07 15:39:13.827: W/YARIAN(30006): requestLayout
11-07 15:39:14.108: W/YARIAN(30006): onLayout
11-07 15:39:14.155: W/YARIAN(30006): requestLayout
11-07 15:39:14.272: W/YARIAN(30006): onLayout
The Android documentation has more information关于测量和布局,但遗憾的是我上面描述的细节不足。
Event Handling and Threading
The basic cycle of a view is as follows:
- An event comes in and is dispatched to the appropriate view. The view handles the event and notifies any listeners.
- If in the course of processing the event, the view's bounds may need to be changed, the view will call requestLayout().
- Similarly, if in the course of processing the event the view's appearance may need to be changed, the view will call invalidate().
- If either requestLayout() or invalidate() were called, the framework will take care of measuring, laying out, and drawing the tree as appropriate.
Note: The entire view tree is single threaded. You must always be on the UI thread when calling any method on any view. If you are doing work on other threads and want to update the state of a view from that thread, you should use a Handler.
关于android - 为什么 onLayout 和 onSizeChanged 在方向改变时被调用两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9696118/
当软键盘出现在屏幕上时,我想使用 onSizeChange 来检测 LinearLayout 中的高度差。我想发布 fullScroll(View.FOCUS_DOWN);在那时候。一个例子将不胜感激
当用户触摸屏幕的某个部分时,是否会调用 onSizeChanged()? 我对 onDraw()、onMeasure() 和 onSizeChanged() 的调用顺序感到困惑。 最佳答案 Andro
这两个事件有什么区别?我想不出任何情况下两者都不会同时被调用,而且 MSDN 也没有启发性。 最佳答案 Answer from Bob Powell [MVP] found on internet (
我有一个以图形方式显示一些数据的应用程序。它创建了两个 View 来绘制图形并将它们添加到我的布局中。每个 View 以不同的方式显示数据,但每个 View 都以相同的方式实现 onSizeChang
我需要获取 View 的高度和宽度,并且我已经按照此处给出的示例对 View 进行子类化并使用 onSizeChanged(...)。但非常奇怪的是 onSizeChanged 给我正确的宽度,但高度
我无法正确调整元素(例如 ListView)的大小。 我有一个用于搜索的 ListActivity,带有仪表板、编辑框和 ListView 。这个想法是在键盘显示时隐藏操作栏。 我扩展了 Linear
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
我创建了一个扩展 Drawable 的自定义类。我正在尝试使用 onSizeChanged() 获取 Drawable 的尺寸,如下所示 public class Circle extends Dra
我有一个 ListView ,它动态分配了不同的数据集。这很好用。我还使 fastScrollEnabled 为真。为了更新 sectionIndexer,我需要调用 list.setFastScro
我注意到在处理来自 Activity 的配置更改时,onLayout 和 onSizeChanged 在方向更改后立即连续调用 两次,从横向->纵向或从纵向->横向.此外,第一个 onLayout/o
我有一个在水平滚动窗口中按列显示文本和图像的 View 。它重排,因此(至少可能)随着内容的变化而调整自己的大小;当软键盘来来去去以及 View 高度发生变化时,它也会重新排列和调整大小(保持大致恒定
我的应用程序当前调用 onCreate() 方法中的一个方法,以便在创建 View 后游戏将启动并运行动画。但是,当我翻转屏幕以在纵向和横向之间切换时,会再次调用此方法。 我已将调用行移至 onSta
我有一个自定义 View ,里面只有一个圆圈。我对它的尺寸有疑问。 我覆盖了 onSizeChanged() 和 onMeasure(),但我担心 onMeasure() 遗漏了一些东西。这个 Vie
我正在编写一个自定义组件,一个强制内部 View 大小的 ViewGroup: myView.getLayoutParams().width = (int) itemSize; myView.getL
我是一名优秀的程序员,十分优秀!