展开/折叠动画:小滞后|| MeasureSpec返回错误的值

yen*_*rah 10 android android-animation

我用的是下面两种方法(启发/从这里复制)到expandcollapse一些TextViewsScrollView通过点击"头" - TextView.

伪布局结构:

<ScrollView>
    <LinearLayout>
        <LinearLayout>
            <!-- some other stuff here -->
        </LinearLayout>
        <TextView "header1"/>
        <View "fancydivider"/>
        <TextView "content1">
        <TextView "header2"/>
        <View "fancydivider"/>
        <TextView "content2">
    </LinearLayout>
</ScrollView>
Run Code Online (Sandbox Code Playgroud)

分频器很简单View,height设置为1dp.内容TextViews风格包括:

    <item name="android:layout_height">0dp</item>
    <item name="android:layout_width">match_parent</item>
Run Code Online (Sandbox Code Playgroud)

和一些边距和填充.

方法在这里:

public static void expand(final View v) {

    //v.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);

    int matchParentMeasureSpec = View.MeasureSpec.makeMeasureSpec(((View) v.getParent()).getWidth(), View.MeasureSpec.EXACTLY);
    int wrapContentMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    v.measure(matchParentMeasureSpec, wrapContentMeasureSpec);

    final int targetHeight = v.getMeasuredHeight();

    // Older versions of android (pre API 21) cancel animations for views with a height of 0.
    v.getLayoutParams().height = 1;
    v.setVisibility(View.VISIBLE);
    Animation a = new Animation() {
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            v.getLayoutParams().height = interpolatedTime == 1
                    ? ViewGroup.LayoutParams.WRAP_CONTENT
                    : (int) (targetHeight * interpolatedTime);
            scrollView.smoothScrollTo(0, (int) (targetHeight * interpolatedTime));
            v.requestLayout();
        }

        @Override
        public boolean willChangeBounds() {
            return true;
        }
    };

    a.setInterpolator(easeInOutQuart);
    a.setDuration(computeDurationFromHeight(v));
    v.startAnimation(a);

}

public static void collapse(final View v) {
    final int initialHeight = v.getMeasuredHeight();

    Animation a = new Animation() {
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            if (interpolatedTime == 1) {
                v.setVisibility(View.GONE);
            } else {
                v.getLayoutParams().height = initialHeight - (int) (initialHeight * interpolatedTime);
                v.requestLayout();
            }
        }

        @Override
        public boolean willChangeBounds() {
            return true;
        }
    };

    a.setInterpolator(easeInOutQuart);
    a.setDuration(computeDurationFromHeight(v));
    v.startAnimation(a);
}

private static int computeDurationFromHeight(View view) {
    // 1dp/ms * multiplier
    return (int) (view.getMeasuredHeight() / view.getContext().getResources().getDisplayMetrics().density) * 4;
}
Run Code Online (Sandbox Code Playgroud)

这里的问题:一切正常 - 直到expand animation达到文本的最后一行 - 如果它上面太少characters,那么它会滞后,跳跃,爆炸? - 但是你要打电话 - 直到完全展开.

Collapsing 似乎工作正常.

我尝试了其他Interpolator值,方法中的另一个乘数computeDurationFromHeight.

一些测试:

    • 4行,在第四行,超过17个字符工作正常,少于18个字符,它滞后.

    • 最后一行的3行和无关数量的字符工作正常.

    • 有时候animation首先是作品expand,而不是第二件作品.

    • 似乎TextView计算错了.multiplier我看到一些高text点,在下一个标题上下跌了0.5秒TextView
    • 删除smoothScrollToin expand不会改变任何东西(当然滚动除外..)
    • 其他内插器也有"打嗝",但更短

    重要:

  • 一些登录applyTransformation(见下文)让我明白了,我看到它final height打印了两次 - 恰好有50点(像素?dp?)的差异.//smoothly increasing height and then: final height = 202 height = 252 final height = 252虽然我得到了targetHeight = 203- 所以height首先计算错误,然后发生一些魔法?

@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
    v.getLayoutParams().height = interpolatedTime == 1
                    ? ViewGroup.LayoutParams.WRAP_CONTENT
                    : (int) (targetHeight * interpolatedTime);
    v.requestLayout();

    scrollView.smoothScrollTo(0, interpolatedTime == 1
                    ? v.getHeight() : (int) (targetHeight * interpolatedTime));

    Log.d("Anim", "height = " + v.getHeight());
    if (interpolatedTime == 1){
        Log.d("Anim", "final height = " + v.getHeight());
    }
}
Run Code Online (Sandbox Code Playgroud)

任何人都可以指出我错过了什么?

ymz*_*ymz 0

这可能会导致因为扩展最后一个元素可能会触发滚动,因为布局的高度变大,因此“推”显示

尝试在底部添加一个高度为 20dp 的 FrameLayout 并尝试观察是否有任何差异