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

Android TextView多文本折叠展开效果

程序员文章站 2024-03-03 19:00:16
最近做项目,效果图要用到textview的折叠,超过一定行数的时候,就会折叠起来,点击可以展开。网上找了一些效果,自己也稍作了修改。便拿来与网友分享分享。 参考文献:a...

最近做项目,效果图要用到textview的折叠,超过一定行数的时候,就会折叠起来,点击可以展开。网上找了一些效果,自己也稍作了修改。便拿来与网友分享分享。
参考文献:android ui实现多行文本折叠展开效果

第一种:通过多个布局组合实现
大概步骤:
- 定义布局,垂直的线性linearlayout布局、textview和imageview。 在layout中定义基本组件。
- 设置textview的高度为指定行数*行高。 不使用maxline的原因是maxline会控制显示文本的行数,不方便后边使用动画展开全部内容。因此这里textview的高度也因该为wrap_content。
- 给整个布局添加点击事件,绑定动画。 点击时,若textview未展开则展开至其实际高度,imageview 旋转;否则回缩至 指定行数*行高 , imageview 旋转缩回。
布局文件:

<?xml version="1.0" encoding="utf-8"?>
<linearlayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:more="http://schemas.android.com/apk/res-auto"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/activity_main"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
 tools:context="com.example.my.textviewdemotest.mainactivity">

 <textview
 android:id="@+id/textview1"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:textcolor="@android:color/black"
 android:textsize="18sp">
 </textview>

 <relativelayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content">

 <textview
 android:id="@+id/expand_text"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="更多"
 android:textsize="18sp"
 android:visibility="gone"/>

 <imageview
 android:id="@+id/expand_view1"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_alignparentright="true"
 android:paddingbottom="5dip"
 android:paddingleft="5dip"
 android:paddingright="5dip"
 android:paddingtop="5dip"
 android:src="@drawable/ic_expand_more_red_700_24dp"
 android:visibility="gone"
 />
 </relativelayout>
 <!-- 第二种方法 -->
 <com.example.my.textviewdemotest.textmoretextview
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:ellipsize="end"
 more:maxline="2"
 more:text="@string/text"
 more:textcolor="@android:color/black"
 more:textsize="18dip">
 </com.example.my.textviewdemotest.textmoretextview>
</linearlayout>

核心代码:

package com.example.my.textviewdemotest;

import android.support.v7.app.appcompatactivity;
import android.os.bundle;
import android.view.view;
import android.view.animation.animation;
import android.view.animation.rotateanimation;
import android.view.animation.transformation;
import android.widget.imageview;
import android.widget.textview;

public class mainactivity extends appcompatactivity implements view.onclicklistener {

 textview text1;
 imageview mimageview1;
 textview expandtext;
 //textmoretextview text2;

 boolean isexpand;//是否已展开的状态
 private int maxdescripline = 3; //textview默认最大展示行数
 private int deltavalue;//默认高度,即前边由maxline确定的高度
 private int startvalue;//起始高度
 private int durationmillis = 350;//动画持续时间

 @override
 protected void oncreate(bundle savedinstancestate) {
 super.oncreate(savedinstancestate);
 setcontentview(r.layout.activity_main);
 text1 = (textview) findviewbyid(r.id.textview1);
 // text2= (textmoretextview) findviewbyid(r.id.text_textview);
 expandtext = (textview) findviewbyid(r.id.expand_text);

 mimageview1 = (imageview) findviewbyid(r.id.expand_view1);
 mimageview1.setonclicklistener(this);

 text1.settext(gettext(r.string.text));
 //第二种可以在这里直接设置文字
 // text2.settext(gettext(r.string.text));
 //这里大家可以根据实际情况来设置文字的高度,做个判断(可能会文字只有一行,也会占据maxdescripline行)
 text1.setheight(text1.getlineheight() * maxdescripline);
 text1.post(new runnable() {
 @override
 public void run() {
 mimageview1.setvisibility(text1.getlinecount() > maxdescripline ? view.visible : view.gone);
 expandtext.setvisibility(text1.getlinecount() > maxdescripline ? view.visible : view.gone);
 }
 });
 }

 @override
 public void onclick(view v) {
 switch (v.getid()) {
 case r.id.expand_view1:
 zhedie(text1, mimageview1);
 break;
 }

 }

 private void zhedie(final textview text, imageview imageview) {
 isexpand = !isexpand;
 text.clearanimation();
 startvalue = text.getheight();
 if (isexpand) {
 /**
 * 折叠动画
 * 从实际高度缩回起始高度
 */
 deltavalue = text.getlineheight() * text.getlinecount() - startvalue;
 rotateanimation animation = new rotateanimation(0, 180, animation.relative_to_self, 0.5f, animation.relative_to_self, 0.5f);
 animation.setduration(durationmillis);
 animation.setfillafter(true);
 imageview.startanimation(animation);
 expandtext.settext("收起");
 } else {
 /**
 * 展开动画
 * 从起始高度增长至实际高度
 */
 deltavalue = text.getlineheight() * maxdescripline - startvalue;
 rotateanimation animation = new rotateanimation(180, 0, animation.relative_to_self, 0.5f, animation.relative_to_self, 0.5f);
 animation.setduration(durationmillis);
 animation.setfillafter(true);
 imageview.startanimation(animation);
 expandtext.settext("更多");
 }
 animation animation = new animation() {
 protected void applytransformation(float interpolatedtime, transformation t) { //根据imageview旋转动画的百分比来显示textview高度,达到动画效果
 text.setheight((int) (startvalue + deltavalue * interpolatedtime));
 }
 };
 animation.setduration(durationmillis);
 text.startanimation(animation);
 }
}

第二种方法,如果用的地方多可以省去很多冗余代码:具体步骤就不直接分析。
核心代码:

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <declare-styleable name="moretextstyle">
 <attr name="textsize" format="dimension"/>
 <attr name="textcolor" format="color"/>
 <attr name="maxline" format="integer" />
 <attr name="text" format="string" />
 </declare-styleable>
</resources>
package com.example.my.textviewdemotest;

import android.content.context;
import android.content.res.typedarray;
import android.graphics.color;
import android.util.attributeset;
import android.util.log;
import android.util.typedvalue;
import android.view.gravity;
import android.view.view;
import android.view.viewtreeobserver;
import android.view.animation.animation;
import android.view.animation.rotateanimation;
import android.view.animation.transformation;
import android.widget.imageview;
import android.widget.linearlayout;
import android.widget.textview;

public class textmoretextview extends linearlayout {
 protected textview contentview;
 protected imageview expandview;

 protected int textcolor;
 protected float textsize;
 protected int maxline;
 protected string text;

 public int defaulttextcolor = color.black;//默认文字颜色
 public int defaulttextsize = 12; //默认文字大小
 public int defaultline = 3; //默认行数

 public textmoretextview(context context, attributeset attrs) {
 super(context, attrs);
 initalize();
 initwithattrs(context, attrs);
 // bindlistener();
 }

 protected void initwithattrs(context context, attributeset attrs) {
 typedarray a = context.obtainstyledattributes(attrs,
 r.styleable.moretextstyle);
 int textcolor = a.getcolor(r.styleable.moretextstyle_textcolor,
 defaulttextcolor);
 textsize = a.getdimensionpixelsize(r.styleable.moretextstyle_textsize, defaulttextsize);
 maxline = a.getint(r.styleable.moretextstyle_maxline, defaultline);
 text = a.getstring(r.styleable.moretextstyle_text);
 bindtextview(textcolor, textsize, maxline, text);
 a.recycle();
 }

 protected void initalize() {
 setorientation(vertical);
 setgravity(gravity.right);
 contentview = new textview(getcontext());
 addview(contentview, layoutparams.match_parent, layoutparams.wrap_content);
 expandview = new imageview(getcontext());
 int padding = dip2px(getcontext(), 5);
 expandview.setpadding(padding, padding, padding, padding);
 expandview.setimageresource(r.drawable.ic_expand_more_red_700_24dp);
 layoutparams llp = new layoutparams(layoutparams.wrap_content, layoutparams.wrap_content);
 addview(expandview, llp);
 }

 protected void bindtextview(int color, float size, final int line, string text) {
 contentview.settextcolor(color);
 contentview.settextsize(typedvalue.complex_unit_px, size);
 contentview.settext(text);
 viewtreeobserver observer = contentview.getviewtreeobserver();
 observer.addongloballayoutlistener(new viewtreeobserver.ongloballayoutlistener() {
 //判断写在这个方法里面能拿到contentview.getlinecount(),否则返回时0;
 @override
 public void ongloballayout() {
 viewtreeobserver obs = contentview.getviewtreeobserver();
 obs.removeglobalonlayoutlistener(this);
 if (contentview.getlinecount() < line) {
 contentview.setheight(contentview.getlineheight() * contentview.getlinecount());
 } else {
 contentview.setheight(contentview.getlineheight() * line);
 bindlistener();//只有在行数大于设定行数才会执行这个方法,做了调整否则会有bug。
 }
 //log.e("aaa", "bindtextview111: " + contentview.getlinecount());//返回0,为什么
 }
 });

 post(new runnable() {
 @override
 public void run() {
 expandview.setvisibility(contentview.getlinecount() > line ? view.visible : view.gone);
 //log.e("aaa", "run: "+contentview.getlinecount() );
 }
 });
 }

 protected void bindlistener() {
 setonclicklistener(new onclicklistener() {
 boolean isexpand;

 @override
 public void onclick(view v) {
 isexpand = !isexpand;
 contentview.clearanimation();
 final int deltavalue;
 final int startvalue = contentview.getheight();
 int durationmillis = 350;
 if (isexpand) {
 deltavalue = contentview.getlineheight() * contentview.getlinecount() - startvalue;
 rotateanimation animation = new rotateanimation(0, 180, animation.relative_to_self, 0.5f, animation.relative_to_self, 0.5f);
 animation.setduration(durationmillis);
 animation.setfillafter(true);
 expandview.startanimation(animation);
 } else {
 deltavalue = contentview.getlineheight() * maxline - startvalue;
 rotateanimation animation = new rotateanimation(180, 0, animation.relative_to_self, 0.5f, animation.relative_to_self, 0.5f);
 animation.setduration(durationmillis);
 animation.setfillafter(true);
 expandview.startanimation(animation);
 }
 animation animation = new animation() {
 protected void applytransformation(float interpolatedtime, transformation t) {
 contentview.setheight((int) (startvalue + deltavalue * interpolatedtime));
 }

 };
 animation.setduration(durationmillis);
 contentview.startanimation(animation);
 }
 });
 }

 public textview gettextview() {
 return contentview;
 }

 public void settext(charsequence charsequence) {
 contentview.settext(charsequence);
 }

 public static int dip2px(context context, float dipvalue) {
 final float scale = context.getresources().getdisplaymetrics().density;
 return (int) (dipvalue * scale + 0.5f);
 }
}

这个类这样就写好了。调用直接在布局文件中引用就行了。

源码下载:http://xiazai.jb51.net/201610/yuanma/androidtextview(jb51.net).rar

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