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

 更新时间:2017年05月24日 17:17:36   作者:w一花一世界w  
这篇文章主要为大家详细介绍了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的多媒体管理库Glide的基本使用示例

    Android的多媒体管理库Glide的基本使用示例

    这篇文章主要介绍了Android的多媒体管理库Glide的基本使用示例,Glide在图片App中的表现非常好,Google旗下的Yelp也在使用,需要的朋友可以参考下
    2016-04-04
  • Flutter 移动程序安全性提高的八个建议

    Flutter 移动程序安全性提高的八个建议

    这篇文章主要为大家介绍了Flutter 移动程序安全性提高建议详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • 解决 INSTALL FAILED CONFLICTING PROVIDER的问题方法

    解决 INSTALL FAILED CONFLICTING PROVIDER的问题方法

    这篇文章主要介绍了解决 INSTALL FAILED CONFLICTING PROVIDER的问题方法的相关资料,需要的朋友可以参考下
    2017-02-02
  • Android实现RecyclerView嵌套流式布局的详细过程

    Android实现RecyclerView嵌套流式布局的详细过程

    最近在做需求的时候,碰到有各种筛选项的界面,下面这篇文章主要给大家介绍了关于Android实现RecyclerView嵌套流式布局的详细过程,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2022-12-12
  • Android开发实现的图片浏览功能示例【放大图片】

    Android开发实现的图片浏览功能示例【放大图片】

    这篇文章主要介绍了Android开发实现的图片浏览功能,结合实例形式分析了Android针对图片的切换显示、透明度、大小调整等相关操作技巧,需要的朋友可以参考下
    2019-04-04
  • Kotlin自定义菜单控件

    Kotlin自定义菜单控件

    这篇文章主要为大家详细介绍了Kotlin自定义菜单控件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-07-07
  • Android实现图片上传蒙层进度条

    Android实现图片上传蒙层进度条

    这篇文章主要为大家详细介绍了Android实现图片上传蒙层进度条,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-09-09
  • 跨平台移动WEB应用开发框架iMAG入门教程

    跨平台移动WEB应用开发框架iMAG入门教程

    这篇文章主要介绍了跨平台移动WEB应用开发框架iMAG入门教程,iMAG最大的特点是生成各移动平台的原生代码,需要的朋友可以参考下
    2014-07-07
  • android实现滑动解锁

    android实现滑动解锁

    这篇文章主要为大家详细介绍了android实现滑动解锁,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • Android ADB简介、安装及使用详解

    Android ADB简介、安装及使用详解

    ADB 全称为 Android Debug Bridge,起到调试桥的作用,是一个客户端-服务器端程序,其中客户端是用来操作的电脑,服务端是 Android 设备,这篇文章介绍Android ADB简介、安装及使用,感兴趣的朋友跟随小编一起看看吧
    2024-01-01

最新评论