欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2023-12-02 22:44:28
背景 在开发过程中,当我们的需求中包含说说或者评论等内容的展示时,我们都会考虑当内容太多时该如何显示。当内容的字数太多,如果全部展示出来可能会影响体验效果,但是又不能只截...

背景

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

效果图:

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();
}

项目地址 ☞ 传送门

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。