为什么我们使用 ViewTreeObserver#addOnGlobalLayoutListener()
Why we use ViewTreeObserver#addOnGlobalLayoutListener()
为什么我们使用ViewTreeObserver
,谁能解释一下?
在下面的代码中 creditsView
是 TextView
对象。通过这整个代码,我理解 "this is to hide some text based on condition",但唯一的问题是我们为什么使用 ViewTreeObserver
?
mainLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightDiff = mainLayout.getRootView().getHeight() - mainLayout.getHeight();
if (heightDiff > 100) {
Utils.appLogger("MyActivity", "keyboard opened");
creditsView.setVisibility(View.GONE);
}
if (heightDiff < 100) {
Utils.appLogger("MyActivity", "keyboard closed");
creditsView.setVisibility(View.VISIBLE);
}
}
});
如果您没有使用 ViewTreeObserver
,那么 mainLayout.getRootView().getHeight()
将只是 return 0px,因为它还没有被布置(参见 getWidth()
and getHeight()
of View
returns 0)。
因此,您要等到视图被测量、布局,然后您才能从中获取 width/height 值。当视图将要在屏幕上布局时,将触发此回调。
不知道为什么,但这是我搜索 KOTLIN 时显示给我的第一页,在通过 Lamda 后我无法删除 listner。
这就是我在 kotlin 中的做法
tvLoginWith.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
@RequiresApi(Build.VERSION_CODES.JELLY_BEAN)
override fun onGlobalLayout() {
tvLoginWith.viewTreeObserver.removeOnGlobalLayoutListener(this)
tvLogin.layoutParams.width = tvLoginWith.width
tvLogin.requestLayout()
}
})
在 kotlin 中执行此操作的好方法(可重用)
像这样创建扩展
fun ViewGroup.addViewObserver(function: () -> Unit) {
val view = this
view.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
view.viewTreeObserver.removeOnGlobalLayoutListener(this)
function.invoke()
}
})
}
并像这样从 activity 使用它
listThumb.addViewObserver {
// your code
}
listThumb 在这种情况下是 recyclerview
为什么我们使用ViewTreeObserver
,谁能解释一下?
在下面的代码中 creditsView
是 TextView
对象。通过这整个代码,我理解 "this is to hide some text based on condition",但唯一的问题是我们为什么使用 ViewTreeObserver
?
mainLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightDiff = mainLayout.getRootView().getHeight() - mainLayout.getHeight();
if (heightDiff > 100) {
Utils.appLogger("MyActivity", "keyboard opened");
creditsView.setVisibility(View.GONE);
}
if (heightDiff < 100) {
Utils.appLogger("MyActivity", "keyboard closed");
creditsView.setVisibility(View.VISIBLE);
}
}
});
如果您没有使用 ViewTreeObserver
,那么 mainLayout.getRootView().getHeight()
将只是 return 0px,因为它还没有被布置(参见 getWidth()
and getHeight()
of View
returns 0)。
因此,您要等到视图被测量、布局,然后您才能从中获取 width/height 值。当视图将要在屏幕上布局时,将触发此回调。
不知道为什么,但这是我搜索 KOTLIN 时显示给我的第一页,在通过 Lamda 后我无法删除 listner。
这就是我在 kotlin 中的做法
tvLoginWith.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
@RequiresApi(Build.VERSION_CODES.JELLY_BEAN)
override fun onGlobalLayout() {
tvLoginWith.viewTreeObserver.removeOnGlobalLayoutListener(this)
tvLogin.layoutParams.width = tvLoginWith.width
tvLogin.requestLayout()
}
})
在 kotlin 中执行此操作的好方法(可重用) 像这样创建扩展
fun ViewGroup.addViewObserver(function: () -> Unit) {
val view = this
view.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
view.viewTreeObserver.removeOnGlobalLayoutListener(this)
function.invoke()
}
})
}
并像这样从 activity 使用它
listThumb.addViewObserver {
// your code
}
listThumb 在这种情况下是 recyclerview