У меня была похожая проблема с похожей ситуацией.
Я должен был создать анимиацию, для которой мне требовалась высота view
, которая подлежит анимации. Внутри этого view
, который является LinearLayout
, может быть дочернее представление типа TextView
. Это TextView
является многострочным, а количество фактически требуемых строк варьируется.
Что бы я ни делал, я просто получил измеренную высоту для вида, как будто TextView
имеет только одну строку для заполнения. Неудивительно, что это работало нормально каждый раз, когда текст оказывался достаточно коротким для одной строки, но не получалось, когда текст был длиннее, чем в строке.
Я обдумал этот ответ: https://stackoverflow.com/a/6157820/854396
Но это не сработало для меня, потому что я не могу получить доступ к встроенному TextView
напрямую отсюда. (Хотя я мог бы повторить, хотя дерево дочерних представлений.)
Посмотрите, как работает мой код:
view
- это вид, который должен быть анимирован. Это LinearLayout
(Окончательное решение будет немного более типичным, сохраняйте здесь)
this
- это пользовательское представление, которое содержит view
и также наследуется от LinearLayout
.
private void expandView( final View view ) {
view.setVisibility(View.VISIBLE);
LayoutParams parms = (LayoutParams) view.getLayoutParams();
final int width = this.getWidth() - parms.leftMargin - parms.rightMargin;
view.measure( MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
final int targetHeight = view.getMeasuredHeight();
view.getLayoutParams().height = 0;
Animation anim = new Animation() {
@Override
protected void applyTransformation( float interpolatedTime, Transformation trans ) {
view.getLayoutParams().height = (int) (targetHeight * interpolatedTime);
view.requestLayout();
}
@Override
public boolean willChangeBounds() {
return true;
}
};
anim.setDuration( ANIMATION_DURATION );
view.startAnimation( anim );
}
Это было почти так, но я допустил еще одну ошибку. В иерархии представлений участвуют два пользовательских представления, которые являются подклассами LinearLayout
, и их xml объединяется с тегом merge
в качестве корневого тега xml. В одном из этих тегов merge
я пропустил установку атрибута android:orientation
на vertical
.
Это не слишком беспокоило саму компоновку, потому что в этом объединенном ViewGroup
был только один дочерний элемент ViewGroup
, и поэтому я фактически не мог видеть неправильную ориентацию на экране. Но он был там и немного нарушил эту логику измерения макета.
В дополнение к вышесказанному может потребоваться избавиться от всех заполнений, связанных с LinearLayout
s и подклассов в иерархии представления. Замените их полями, даже если вам нужно обернуть вокруг них другой макет, чтобы он выглядел одинаково.