绘制前调整视图大小
Resizing Views before drawing
在我的布局中,我有一个包含 4 个自定义 ImageView 的 GridView。我将 GridView 的可见性设置为不可见,直到首先调整所有 ImageView 的大小,但是当显示 GridView 时,有一个短暂的闪烁,ImageView 仍然没有变化。
每个 ImageView 创建单独的侦听器以缩放其大小:
//Setting new params as half of parent's size and increasing counter
if (getViewTreeObserver().isAlive()) {
final ViewTreeObserver viewTreeObserver = getViewTreeObserver();
viewTreeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
getViewTreeObserver().removeOnPreDrawListener(this);
View parent = (View) getParent();
int dimension = Math.min(parent.getWidth(), parent.getHeight()) / 2;
mThisImageView.setLayoutParams(new AbsListView.LayoutParams(dimension, dimension));
ResizeCounter.setCounter(ResizeCounter.getCounter() + 1);
return true;
}
});
}
//Activity listens to the moment when all ImageViews have been resized
ResizeCounter.addCounterListener(new OnResizeCounterChangeListener() {
@Override
public void onResizeCounterChanged() {
if (ResizeCounter.getCounter() == 4) {
mAnswerGridView.setVisibility(View.VISIBLE);
}
}
});
我还尝试在 onGlobalLayout 方法中调整它们的大小(相同的结果)并覆盖 onMeasure 方法(此时父视图仍然为 null)。
我怀疑现在更改 onPreDraw() 中的视图为时已晚,但是是否有一种方法可以更早地在其中调用,我可以确定所有视图都已被测量?
尝试在 mAnswerGridView.setVisibility(View.VISIBLE);
之前调用 mAnswerGridView.requestLayout()
这可能行不通,因为正如 Android Developers
中所述
This will schedule a layout pass of the view tree.
所以你最好强制重新布局:
relayoutChildren(View view) {
view.measure(
View.MeasureSpec.makeMeasureSpec(view.getMeasuredWidth(), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(view.getMeasuredHeight(), View.MeasureSpec.EXACTLY));
view.layout(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); }
我创建了一个处理程序,可以在调用 requestLayout 后立即安排设置可见性。
在这种情况下效果很好。
ResizeCounter.addCounterListener(new OnResizeCounterChangeListener() {
@Override
public void onResizeCounterChanged() {
if (ResizeCounter.getCounter() == 4) {
mAnswerGridView.requestLayout();
Handler handler = new Handler();
handler.post(new Runnable() {
@Override
public void run() {
mAnswerGridView.setVisibility(View.VISIBLE);
}
});
}
}
});
在我的布局中,我有一个包含 4 个自定义 ImageView 的 GridView。我将 GridView 的可见性设置为不可见,直到首先调整所有 ImageView 的大小,但是当显示 GridView 时,有一个短暂的闪烁,ImageView 仍然没有变化。
每个 ImageView 创建单独的侦听器以缩放其大小:
//Setting new params as half of parent's size and increasing counter
if (getViewTreeObserver().isAlive()) {
final ViewTreeObserver viewTreeObserver = getViewTreeObserver();
viewTreeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
getViewTreeObserver().removeOnPreDrawListener(this);
View parent = (View) getParent();
int dimension = Math.min(parent.getWidth(), parent.getHeight()) / 2;
mThisImageView.setLayoutParams(new AbsListView.LayoutParams(dimension, dimension));
ResizeCounter.setCounter(ResizeCounter.getCounter() + 1);
return true;
}
});
}
//Activity listens to the moment when all ImageViews have been resized
ResizeCounter.addCounterListener(new OnResizeCounterChangeListener() {
@Override
public void onResizeCounterChanged() {
if (ResizeCounter.getCounter() == 4) {
mAnswerGridView.setVisibility(View.VISIBLE);
}
}
});
我还尝试在 onGlobalLayout 方法中调整它们的大小(相同的结果)并覆盖 onMeasure 方法(此时父视图仍然为 null)。
我怀疑现在更改 onPreDraw() 中的视图为时已晚,但是是否有一种方法可以更早地在其中调用,我可以确定所有视图都已被测量?
尝试在 mAnswerGridView.setVisibility(View.VISIBLE);
mAnswerGridView.requestLayout()
这可能行不通,因为正如 Android Developers
中所述This will schedule a layout pass of the view tree.
所以你最好强制重新布局:
relayoutChildren(View view) {
view.measure(
View.MeasureSpec.makeMeasureSpec(view.getMeasuredWidth(), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(view.getMeasuredHeight(), View.MeasureSpec.EXACTLY));
view.layout(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); }
我创建了一个处理程序,可以在调用 requestLayout 后立即安排设置可见性。
在这种情况下效果很好。
ResizeCounter.addCounterListener(new OnResizeCounterChangeListener() {
@Override
public void onResizeCounterChanged() {
if (ResizeCounter.getCounter() == 4) {
mAnswerGridView.requestLayout();
Handler handler = new Handler();
handler.post(new Runnable() {
@Override
public void run() {
mAnswerGridView.setVisibility(View.VISIBLE);
}
});
}
}
});