最近做项目,效果图要用到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
您可能感兴趣的文章:Android UI实现多行文本折叠展开效果Android TextView实现多文本折叠、展开效果Android中RecyclerView实现多级折叠列表效果(二)Android中RecyclerView实现多级折叠列表效果(TreeRecyclerView)Android折叠式Toolbar使用完全解析(CollapsingToolbarLayout)android给RecyclerView加上折叠的效果示例Android中FoldingLayout折叠布局的用法及实战全攻略Android TextView仿微信可折叠效果Android显示全文折叠控件使用方法详解Android开发实现的文本折叠点击展开功能示例