Android TextView实现多文本折叠、展开效果

背景

在开发过程中,当我们的需求中包含说说或者评论等内容的展示时,我们都会考虑当内容太多时该如何显示。当内容的字数太多,如果全部展示出来可能会影响体验效果,但是又不能只截取一部分内容进行展示,此时就需要考虑使用多行显示折叠的效果来实现。

效果图:

使用

1.布局文件调用

<LinearLayout

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

<com.wiggins.expandable.widget.MoreLineTextView

android:id="@+id/tv_more_line_short"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="@color/white"

android:padding="@dimen/padding_small"

app:clickAll="true"

app:textColor="@color/red" />

<View style="@style/spaceLine" />

<com.wiggins.expandable.widget.expandable.ExpandableTextView

android:id="@+id/tv_expandable_short"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="@color/white"

android:ellipsize="end"

android:padding="@dimen/padding_small"

android:textColor="@color/blue"

app:allClickable="false"

app:contentTextColor="@color/blue"

app:isDisplayIcon="false"

app:maxCollapsedLines="4" />

<View style="@style/spaceLine" />

<com.wiggins.expandable.widget.MoreLineTextView

android:id="@+id/tv_more_line_long"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="@color/white"

android:padding="@dimen/padding_small"

app:clickAll="true"

app:textColor="@color/red" />

<View style="@style/spaceLine" />

<com.wiggins.expandable.widget.expandable.ExpandableTextView

android:id="@+id/tv_expandable_long"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="@color/white"

android:ellipsize="end"

android:padding="@dimen/padding_small"

android:textColor="@color/blue"

app:allClickable="false"

app:contentTextColor="@color/blue"

app:isDisplayIcon="false"

app:maxCollapsedLines="4" />

</LinearLayout>

2.Java文件调用

private void initData() {

mTvMoreLineShort.setText(Constant.content1);

mTvExpandableShort.setText(Constant.content2);

mTvMoreLineLong.setText(Constant.content3);

mTvExpandableLong.setText(Constant.content4);

}

MoreLineTextView使用

1.在attr.xml中定义属性

<declare-styleable name="MoreTextStyle">

<!--内容大小-->

<attr name="textSize" format="dimension" />

<!--内容颜色-->

<attr name="textColor" format="color" />

<!--内容默认最大行数-->

<attr name="maxLine" format="integer" />

<!--展开/收起图标-->

<attr name="expandIcon" format="reference" />

<!--展开/收起动画执行时间-->

<attr name="durationMillis" format="integer" />

<!--可点击区域,默认展开/收起区域可点击-->

<attr name="clickAll" format="boolean" />

</declare-styleable>

2.是否显示折叠效果

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

// 如果没有变化,测量并返回

if (!mRelayout || getVisibility() == View.GONE) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

return;

}

mRelayout = false;

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

// 内容区域初始显示行高

mTvContent.setHeight(mTvContent.getLineHeight() * (mMaxLine > mTvContent.getLineCount() ? mTvContent.getLineCount() : mMaxLine));

mLlExpand.post(new Runnable() {

@Override

public void run() {

// 是否显示折叠效果

mLlExpand.setVisibility(mTvContent.getLineCount() > mMaxLine ? View.VISIBLE : View.GONE);

}

});

}

3.设置显示内容

/**

* @Description 设置显示内容

*/

public void setText(String str) {

mRelayout = true;

mTvContent.setText(str);

setVisibility(TextUtils.isEmpty(str) ? View.GONE : View.VISIBLE);

}

4.展开/收起动画

@Override

public void onClick(View v) {

if (mTvContent.getLineCount() <= mMaxLine) {

return;

}

isExpand = !isExpand;

mTvContent.clearAnimation();

final int deltaValue;

final int startValue = mTvContent.getHeight();

if (isExpand) {

deltaValue = mTvContent.getLineHeight() * mTvContent.getLineCount() - startValue;//计算要展开高度

RotateAnimation animation = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

animation.setDuration(mDurationMillis);

animation.setFillAfter(true);

mIvExpand.startAnimation(animation);

mTvExpand.setText(getContext().getString(R.string.collapse));

} else {

deltaValue = mTvContent.getLineHeight() * mMaxLine - startValue;//为负值,收缩的高度

RotateAnimation animation = new RotateAnimation(180, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

animation.setDuration(mDurationMillis);

animation.setFillAfter(true);

mIvExpand.startAnimation(animation);

mTvExpand.setText(getContext().getString(R.string.expand));

}

Animation animation = new Animation() {

protected void applyTransformation(float interpolatedTime, Transformation t) {

//interpolatedTime:为当前动画帧对应的相对时间,值总在0-1之间,原始长度+高度差*(从0到1的渐变)即表现为动画效果

mTvContent.setHeight((int) (startValue + deltaValue * interpolatedTime));

}

};

animation.setDuration(mDurationMillis);

mTvContent.startAnimation(animation);

}

ExpandableTextView使用

1.在attr.xml中定义属性

<declare-styleable name="ExpandableTextView">

<!--内容默认最大行数,超过隐藏-->

<attr name="maxCollapsedLines" format="integer" />

<!--展开/收起动画执行时间-->

<attr name="animDuration" format="integer" />

<!--展开图片-->

<attr name="expandDrawable" format="reference" />

<!--收起图片-->

<attr name="collapseDrawable" format="reference" />

<!--内容颜色-->

<attr name="contentTextColor" format="color" />

<!--内容大小-->

<attr name="contentTextSize" format="dimension" />

<!--收起/展开颜色-->

<attr name="collapseExpandTextColor" format="color" />

<!--收起/展开大小-->

<attr name="collapseExpandTextSize" format="dimension" />

<!--收起文字-->

<attr name="textCollapse" format="string" />

<!--展开文字-->

<attr name="textExpand" format="string" />

<!--可点击区域,默认展开/收起区域可点击-->

<attr name="allClickable" format="boolean" />

<!--是否显示展开/收起图标,默认显示-->

<attr name="isDisplayIcon" format="boolean" />

<!--收起/展开位置,默认左边-->

<attr name="collapseExpandGrarity">

<flag name="left" value="3" />

<flag name="right" value="5" />

</attr>

<!--收起/展开图标位置,默认右边-->

<attr name="drawableGrarity">

<flag name="left" value="3" />

<flag name="right" value="5" />

</attr>

</declare-styleable>

2.是否显示折叠效果

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

// 如果没有变化,测量并返回

if (!mRelayout || getVisibility() == View.GONE) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

return;

}

mRelayout = false;

// Setup with optimistic case

// i.e. Everything fits. No button needed

mLlExpand.setVisibility(View.GONE);

mTvContent.setMaxLines(Integer.MAX_VALUE);

// Measure

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

//如果内容真实行数小于等于最大行数,不处理

if (mTvContent.getLineCount() <= mMaxCollapsedLines) {

return;

}

// 获取内容tv真实高度(含padding)

mTextHeightWithMaxLines = getRealTextViewHeight(mTvContent);

// 如果是收起状态,重新设置最大行数

if (mCollapsed) {

mTvContent.setMaxLines(mMaxCollapsedLines);

}

mLlExpand.setVisibility(View.VISIBLE);

// Re-measure with new setup

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

if (mCollapsed) {

// Gets the margin between the TextView's bottom and the ViewGroup's bottom

mTvContent.post(new Runnable() {

@Override

public void run() {

mMarginBetweenTxtAndBottom = getHeight() - mTvContent.getHeight();

}

});

// 保存这个容器的测量高度

mCollapsedHeight = getMeasuredHeight();

}

}

3.设置显示内容

/**

* @Description 设置显示内容

*/

public void setText(CharSequence text) {

mRelayout = true;

mTvContent.setText(text);

setVisibility(TextUtils.isEmpty(text) ? View.GONE : View.VISIBLE);

}

4.展开/收起动画

@Override

public void onClick(View view) {

if (mLlExpand.getVisibility() != View.VISIBLE) {

return;

}

mCollapsed = !mCollapsed;

// 修改收起/展开图标、文字

setDrawbleAndText();

// 保存位置状态

if (mCollapsedStatus != null) {

mCollapsedStatus.put(mPosition, mCollapsed);

}

// 执行展开/收起动画

mAnimating = true;

ValueAnimator valueAnimator;

if (mCollapsed) {

valueAnimator = new ValueAnimator().ofInt(getHeight(), mCollapsedHeight);

} else {

mCollapsedHeight = getHeight();

valueAnimator = new ValueAnimator().ofInt(getHeight(), getHeight() + mTextHeightWithMaxLines - mTvContent.getHeight());

}

valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator valueAnimator) {

int animatedValue = (int) valueAnimator.getAnimatedValue();

mTvContent.setMaxHeight(animatedValue - mMarginBetweenTxtAndBottom);

getLayoutParams().height = animatedValue;

requestLayout();

}

});

valueAnimator.addListener(new Animator.AnimatorListener() {

@Override

public void onAnimationStart(Animator animator) {

}

@Override

public void onAnimationEnd(Animator animator) {

// 动画结束后发送结束的信号,清除动画标志

mAnimating = false;

// 通知监听

if (mListener != null) {

mListener.onExpandStateChanged(mTvContent, !mCollapsed);

}

}

@Override

public void onAnimationCancel(Animator animator) {

}

@Override

public void onAnimationRepeat(Animator animator) {

}

});

valueAnimator.setDuration(mAnimationDuration);

valueAnimator.start();

}

项目地址 ☞ 传送门

以上是 Android TextView实现多文本折叠、展开效果 的全部内容, 来源链接: utcz.com/z/337035.html

回到顶部