动画MaxLines和Ellipsize

时间:2013-06-13 08:15:40

标签: android

我有textview,其中包含文本的一部分。当用户单击箭头时,textview会调整大小以显示全文。请参阅下面的图片以获取示例: collapsed

expanded

TextView具有wrap_content高度,当折叠时,maxLines =" 4"。

箭头的onClick包含以下代码:

        if (isExpanded) {
            btnToggle.setImageDrawable(getResources().getDrawable(
                    R.drawable.arrow_down));
            tvText.setMaxLines(4);
            tvText.setEllipsize(TruncateAt.END);
        } else {
            btnToggle.setImageDrawable(getResources().getDrawable(
                    R.drawable.arrow_up));
            tvText.setMaxLines(Integer.MAX_VALUE);
            tvText.setEllipsize(null);
        }
        isExpanded = !isExpanded;

此代码有效,但不是动画。我需要为扩展设置动画,因此TextView会将其设置为全高度。 我找不到像MaxLines这样的动画属性。谁可以帮助我?

4 个答案:

答案 0 :(得分:52)

您可以使用ObjectAnimator

来实现此目的
ObjectAnimator animation = ObjectAnimator.ofInt(
        tvText,
        "maxLines", 
        25);
animation.setDuration(4000);
animation.start();

这会将“tvText”TextView的“maxLines”属性从最初设置的任何内容增加到25,在4000毫秒的时间内。

查看更多herehere

答案 1 :(得分:4)

虽然动画maxLines有效,但结果有点不稳定,因为你的视野高度跳跃很多。

int startHeight = content.getMeasuredHeight();
content.setMaxLines(Integer.MAX_VALUE);
content.measure(
            View.MeasureSpec.makeMeasureSpec(parent.getWidth(), View.MeasureSpec.AT_MOST),
            View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
int endHeight = content.getMeasuredHeight();

contentTextViewmaxLines设置为2.现在您可以设置TextView高度的动画。 编辑:TextView滚动时,如果它不能垂直放入内容,则需要解决方法。 setMovementMethod(null)禁用滚动,但它也会禁用链接点击。因为Android。

答案 2 :(得分:1)

接受的答案根本就是错误的,因为它会强制调用 TextView.setMaxLines() lot 次,并且无理由地使用相同的值,使得生成的动画生涩

您可以使用带有lastValue标志的简单ValueAnimator:

    ValueAnimator animator = ValueAnimator.ofInt(fromThisLineCount, toThisLineCount).setDuration(250);

    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        int lastValue = -1;

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int value = (int) animation.getAnimatedValue();

            if (value == lastValue) {
                return;
            }

            lastValue = value;

            yourTextView.setMaxLines(value);
        }
    });

    animator.start();

请记住,动画每次都会添加/删除1个整行,因此如果动画持续时间太长或者只影响几行,它仍然会显得生涩。最好的方法是创建自定义视图并进行适当的测量 onMeasure (参见例如https://github.com/Manabu-GT/ExpandableTextView)。

答案 3 :(得分:0)

所有其他解决方案对我来说效果都不理想。动画不连贯甚至闪烁。

我选择做的是设置layoutParams高度的动画。此解决方案可能并不适合每种情况,但对我来说似乎很好用。这是一个演示:

enter image description here

MainActivity.kt

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val expectedWidthOfTextView = resources.displayMetrics.widthPixels
        val originalMaxLines = textView.maxLines
        if (originalMaxLines < 0 || originalMaxLines == Integer.MAX_VALUE)
            Log.d("AppLog", "already unbounded textView maxLines")
        else {
            textView.maxLines = Integer.MAX_VALUE
            textView.measure(
                View.MeasureSpec.makeMeasureSpec(expectedWidthOfTextView, View.MeasureSpec.AT_MOST),
                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
            )
            val measuredLineCount = textView.lineCount
            val measuredTargetHeight = textView.measuredHeight
            Log.d("AppLog", "lines:$measuredLineCount/$originalMaxLines")
            textView.maxLines = originalMaxLines
            if (measuredLineCount <= originalMaxLines)
                Log.d("AppLog", "fit in original maxLines")
            else {
                Log.d("AppLog", "exceeded original maxLines")
                textView.setOnClickListener {
                    textView.setOnClickListener(null)
                    textView.maxLines = Integer.MAX_VALUE
                    val layoutParams = textView.layoutParams
                    val animation = ValueAnimator.ofInt(textView.height, measuredTargetHeight)
                    animation.addUpdateListener { valueAnimator ->
                        val value: Int = valueAnimator.animatedValue as Int
                        layoutParams.height = value
                        textView.requestLayout()
                    }
                    animation.start()
                    layoutParams.height = textView.height
                }
            }
        }

    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent" android:orientation="vertical" android:gravity="center_horizontal"
        android:layout_height="match_parent" android:animateLayoutChanges="true"
        tools:context=".MainActivity">

    <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content"
               android:src="@android:drawable/sym_def_app_icon"/>

    <TextView
            android:id="@+id/textView" android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:ellipsize="end" android:maxLines="4" android:clickable="true" android:focusable="true"
            android:paddingEnd="16dp" android:paddingStart="16dp"
            android:textColor="#c1000000" android:textSize="14sp"
            android:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."/>

    <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content"
               android:src="@android:drawable/sym_def_app_icon"/>
</LinearLayout>