Я думаю, что система макетов в Android не была разработана для решения такой проблемы, которая, вероятно, предложила бы изменить проблему.
Тем не менее, я думаю, что главная проблема здесь заключается в том, что ваш взгляд на самом деле не отвечает за вычисление его собственного роста.Это всегда родитель представления, который вычисляет размеры его дочерних элементов.Они могут высказать свое «мнение», но, в конце концов, как и в реальной жизни, они не имеют никакого реального права голоса в этом вопросе.
Это может предложить взглянуть на родителя представленияили, скорее, первый родитель, размеры которого не зависят от размеров его потомков.Этот родитель может отказаться от размещения (и, следовательно, отрисовки) своих дочерних элементов, пока все дочерние элементы не закончили свою фазу измерения (что происходит в отдельном потоке).Как только они это сделают, родитель запрашивает новую фазу макета и размещает свои дочерние элементы без необходимости их повторного измерения.
Важно, чтобы измерения дочерних элементов не влияли на измерение указанного родителя, поэтомучто он может «впитать» вторую фазу макета без необходимости переоценки своих потомков и, таким образом, урегулировать процесс компоновки.
[править] Если немного углубиться в это, я могу подумать одовольно простое решение, у которого действительно есть только один минус.Вы можете просто создать AsyncView
, который расширяет ViewGroup
и, подобно ScrollView
, содержит только одного дочернего элемента, который всегда заполняет все его пространство.AsyncView
не учитывает размер дочернего элемента для его собственного размера и в идеале просто заполняет доступное пространство.Все, что делает AsyncView
, это оборачивает вызов измерения своего дочернего элемента в отдельный поток, который возвращает к представлению, как только измерение выполнено.
Внутри этого представления вы можете в значительной степени поместить все, что захотите, включая другие макеты.Неважно, насколько глубоко «проблемный взгляд» находится в иерархии.Единственным недостатком будет то, что ни один из потомков не будет визуализирован, пока все потомки не будут измерены.Но вы, вероятно, захотите показать какую-то анимацию загрузки, пока представление не будет готово в любом случае.
«Проблемное представление» не должно быть связано с многопоточностью.Он может измерять себя точно так же, как и любой другой вид, занимая столько времени, сколько ему нужно.
[edit2] Я даже потрудился взломать быструю реализацию:
package com.example.asyncview;
import android.content.Context;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
public class AsyncView extends ViewGroup {
private AsyncTask<Void, Void, Void> mMeasureTask;
private boolean mMeasured = false;
public AsyncView(Context context) {
super(context);
}
public AsyncView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
for(int i=0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.layout(0, 0, child.getMeasuredWidth(), getMeasuredHeight());
}
}
@Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if(mMeasured)
return;
if(mMeasureTask == null) {
mMeasureTask = new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... objects) {
for(int i=0; i < getChildCount(); i++) {
measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
mMeasured = true;
mMeasureTask = null;
requestLayout();
}
};
mMeasureTask.execute();
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if(mMeasureTask != null) {
mMeasureTask.cancel(true);
mMeasureTask = null;
}
mMeasured = false;
super.onSizeChanged(w, h, oldw, oldh);
}
}
См. https://github.com/wetblanket/AsyncView для рабочего примера