TextView实现展开收起的效果

作者: alighters | 来源:发表于2015-11-08 23:07 被阅读11201次

在做Android的过程中,我们经常会遇到TextView显示文本过长的情况,这里我们以开源库ExpandableTextView为例,对其的实现做一讲解:

实现原理描述:expandableTextView继承自LinearLayout(只支持竖直方向),包含TextView和ImageButton两个子view,通过参数 maxCollapsedLines来设置折叠最大的行数,在onMeasure方法中,判断textView的行数,来进行textview折叠和收起状态的设定;另外,收起和展开的效果则针对TextView的高度进行动画。

** 具体使用方法** :

  • 布局:使用ExpandableTextView作为TextView(指定id为expandable_text)和ImageButton(指定id为expand_collapse)的父View.
  • 设值:设定ExpandableText的maxCollapsedLines为折叠的行数。

** 实现细节:**

  • ExpandableTextView是如何确定子view的?
    答:是通过重写ViewGroup一个回调onFinishInflate()方法,来获取对应的子view(TextView跟ImageButton).
  • OnMeasure中执行了哪些操作?
    答:具体是进行根据展开折叠状态的判断,来设定当前textView的行数以及点击事件和imageButton的显示状态。具体代码如下:
@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

// If no change, measure and return

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

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

return;

}

mRelayout = false;

// Setup with optimistic case

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

mButton.setVisibility(View.GONE);

mTv.setMaxLines(Integer.MAX_VALUE);

// Measure

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

// If the text fits in collapsed mode, we are done.

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

return;

}

// Saves the text height w/ max lines

mTextHeightWithMaxLines = getRealTextViewHeight(mTv);

// Doesn't fit in collapsed mode. Collapse text view as needed. Show

// button.

if (mCollapsed) {

mTv.setMaxLines(mMaxCollapsedLines);

}

mButton.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

mTv.post(new Runnable() {

@Override

public void run() {

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

}

});

// Saves the collapsed height of this ViewGroup

mCollapsedHeight = getMeasuredHeight();

}

}
  • 收起展开动画的实现?
    答:这里实现定义了一个扩展收起的动画,主要针对整个View的高度做动画,因为我们已经知道了view折叠之后的高度和扩展之后的高度(可以算出来),然后修改布局就好。
    具体的动画代码如下:
class ExpandCollapseAnimation extends Animation {

private final View mTargetView;

private final int mStartHeight;

private final int mEndHeight;

public ExpandCollapseAnimation(View view, int startHeight, int endHeight) {

mTargetView = view;

mStartHeight = startHeight;

mEndHeight = endHeight;

setDuration(mAnimationDuration);

}

@Override

protected void applyTransformation(float interpolatedTime, Transformation t) {

final int newHeight = (int)((mEndHeight - mStartHeight) * interpolatedTime + mStartHeight);

mTv.setMaxHeight(newHeight - mMarginBetweenTxtAndBottom);

if (Float.compare(mAnimAlphaStart, 1.0f) != 0) {

applyAlphaAnimation(mTv, mAnimAlphaStart + interpolatedTime * (1.0f - mAnimAlphaStart));

}

mTargetView.getLayoutParams().height = newHeight;

mTargetView.requestLayout();

}

@Override

public void initialize( int width, int height, int parentWidth, int parentHeight ) {

super.initialize(width, height, parentWidth, parentHeight);

}

@Override

public boolean willChangeBounds( ) {

return true;

}

};

动画调用的代码是在view的点击事件回调中:

Animation animation;

if (mCollapsed) {

animation = new ExpandCollapseAnimation(this, getHeight(), mCollapsedHeight);

} else {

animation = new ExpandCollapseAnimation(this, getHeight(), getHeight() +

mTextHeightWithMaxLines - mTv.getHeight());

}

我们这里就会产生一个疑惑,mTextHeightWithMaxLines(文本全部显示对应的textview的高度)是怎么获取到的呢?相应获取的代码如下:

private static int getRealTextViewHeight(@NonNull TextView textView) {

int textHeight = textView.getLayout().getLineTop(textView.getLineCount());

int padding = textView.getCompoundPaddingTop() + textView.getCompoundPaddingBottom();

return textHeight + padding;

}

这里有两个主要的方法,getLineCount获取textview的行数,getLineTop获取textview的行高。
至此,我们就可以实现整个expandableTextView的收起展开的效果了。

  • 如何在ListView中确保当前textView的状态?
    我们知道在多列表view中,都要考虑到view重用的问题,若是expandableTextView不能在这种情况下使用的话,那对我们的使用情景就大有限制了。在这里,在调用setText的时候,提供了SparseBooleanArray collapseStatus和int position来记录当前的展开收起状态了。所以,就需要我们在我们的adapter中也使用相同的数据结构了。具体代码如下:
public void setText(@Nullable CharSequence text, @NonNull SparseBooleanArray collapsedStatus, int position) {

mCollapsedStatus = collapsedStatus;

mPosition = position;

boolean isCollapsed = collapsedStatus.get(position, true);

clearAnimation();

mCollapsed = isCollapsed;

mButton.setImageDrawable(mCollapsed ? mExpandDrawable : mCollapseDrawable);

setText(text);

getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;

requestLayout();

}

最后,我们关于ExpandableTextView的实现原理就讲完了,具体还有疑问的话,可以提出一起讨论。另外,代码的格式没有做缩进,大家多多担待。灰常感谢。。

相关文章

  • TextView实现展开收起的效果

    在做Android的过程中,我们经常会遇到TextView显示文本过长的情况,这里我们以开源库Expandable...

  • TextView展开收起 ReadMoreTextView

    咳咳,先来一张 简陋到新天际的 效果图 密恐的请自备氧气 废话少说 先上 原文链接 ReadMoreTextVie...

  • 自定义展开收起TextView

    功能 展开,收起TextView 支持:maxLineCount:最大的行数,超过后显示收起 支持:collaps...

  • 开发收集

    自定义可展开收起TextView,展开收起按钮紧跟文本内容https://blog.csdn.net/u01445...

  • 可展开/收起的TextView

    在Android开发中,经常会用碰到这样的需求:描述信息比较长,默认情况下只显示几行,点击可以展开查看所有内容,再...

  • 2021-04-15 vue css 实现多行文本溢出超过指定

    1.文本 展开收起效果图: 收起时效果 展开时效果使用的uView插件,用到里面的图标代码: 1.2 更新展开收起...

  • 小程序 — 展开/收起

    前言:本章说下文字内容的展开与收起的实现,要实现这么一个效果:当收起的时候隐藏并显示省略号,当展开的时候显示全部文...

  • Android可展开收起的textview

    效果如图下: 文字可自由配置,字体颜色可定义,可定义首次展示状态等等。集成简单,高度可定制化。1.整个封装在Exp...

  • Angular动画效果篇

    problem:在angularjs框架中实现展开收起的动画效果 Try: 1.要引入anguar-animate...

  • Android 自定义View之展开收起的Layout

    效果 分析 效果图来看,点击事件触发view的展开收起,并在收起状态下保留了第一个子view显示,这个展开收起其实...

网友评论

    本文标题:TextView实现展开收起的效果

    本文链接:https://www.haomeiwen.com/subject/akpchttx.html