Android TextView实现多文本折叠、展开效果
程序员文章站
2023-12-12 18:04:22
背景
在开发过程中,当我们的需求中包含说说或者评论等内容的展示时,我们都会考虑当内容太多时该如何显示。当内容的字数太多,如果全部展示出来可能会影响体验效果,但是又不能只截...
背景
在开发过程中,当我们的需求中包含说说或者评论等内容的展示时,我们都会考虑当内容太多时该如何显示。当内容的字数太多,如果全部展示出来可能会影响体验效果,但是又不能只截取一部分内容进行展示,此时就需要考虑使用多行显示折叠的效果来实现。
效果图:
使用
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(); }
项目地址 ☞ 传送门
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。