Android TextView多文本折叠展开效果
最近做项目,效果图要用到TextView的折叠,超过一定行数的时候,就会折叠起来,点击可以展开。网上找了一些效果,自己也稍作了修改。便拿来与网友分享分享。
参考文献:AndroidUI实现多行文本折叠展开效果
第一种:通过多个布局组合实现
大概步骤:
-定义布局,垂直的线性LinearLayout布局、TextView和ImageView。在layout中定义基本组件。
-设置TextView的高度为指定行数*行高。不使用maxLine的原因是maxLine会控制显示文本的行数,不方便后边使用动画展开全部内容。因此这里TextView的高度也因该为wrap_content。
-给整个布局添加点击事件,绑定动画。点击时,若TextView未展开则展开至其实际高度,imageView旋转;否则回缩至指定行数*行高,imageView旋转缩回。
布局文件:
<?xmlversion="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>
核心代码:
packagecom.example.my.textviewdemotest;
importandroid.support.v7.app.AppCompatActivity;
importandroid.os.Bundle;
importandroid.view.View;
importandroid.view.animation.Animation;
importandroid.view.animation.RotateAnimation;
importandroid.view.animation.Transformation;
importandroid.widget.ImageView;
importandroid.widget.TextView;
publicclassMainActivityextendsAppCompatActivityimplementsView.OnClickListener{
TextViewtext1;
ImageViewmImageView1;
TextViewexpandText;
//TextMoreTextViewtext2;
booleanisExpand;//是否已展开的状态
privateintmaxDescripLine=3;//TextView默认最大展示行数
privateintdeltaValue;//默认高度,即前边由maxLine确定的高度
privateintstartValue;//起始高度
privateintdurationMillis=350;//动画持续时间
@Override
protectedvoidonCreate(BundlesavedInstanceState){
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(newRunnable(){
@Override
publicvoidrun(){
mImageView1.setVisibility(text1.getLineCount()>maxDescripLine?View.VISIBLE:View.GONE);
expandText.setVisibility(text1.getLineCount()>maxDescripLine?View.VISIBLE:View.GONE);
}
});
}
@Override
publicvoidonClick(Viewv){
switch(v.getId()){
caseR.id.expand_view1:
zheDie(text1,mImageView1);
break;
}
}
privatevoidzheDie(finalTextViewtext,ImageViewimageView){
isExpand=!isExpand;
text.clearAnimation();
startValue=text.getHeight();
if(isExpand){
/**
*折叠动画
*从实际高度缩回起始高度
*/
deltaValue=text.getLineHeight()*text.getLineCount()-startValue;
RotateAnimationanimation=newRotateAnimation(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;
RotateAnimationanimation=newRotateAnimation(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("更多");
}
Animationanimation=newAnimation(){
protectedvoidapplyTransformation(floatinterpolatedTime,Transformationt){//根据ImageView旋转动画的百分比来显示textview高度,达到动画效果
text.setHeight((int)(startValue+deltaValue*interpolatedTime));
}
};
animation.setDuration(durationMillis);
text.startAnimation(animation);
}
}
第二种方法,如果用的地方多可以省去很多冗余代码:具体步骤就不直接分析。
核心代码:
<?xmlversion="1.0"encoding="utf-8"?> <resources> <declare-styleablename="MoreTextStyle"> <attrname="textSize"format="dimension"/> <attrname="textColor"format="color"/> <attrname="maxLine"format="integer"/> <attrname="text"format="string"/> </declare-styleable> </resources>
packagecom.example.my.textviewdemotest;
importandroid.content.Context;
importandroid.content.res.TypedArray;
importandroid.graphics.Color;
importandroid.util.AttributeSet;
importandroid.util.Log;
importandroid.util.TypedValue;
importandroid.view.Gravity;
importandroid.view.View;
importandroid.view.ViewTreeObserver;
importandroid.view.animation.Animation;
importandroid.view.animation.RotateAnimation;
importandroid.view.animation.Transformation;
importandroid.widget.ImageView;
importandroid.widget.LinearLayout;
importandroid.widget.TextView;
publicclassTextMoreTextViewextendsLinearLayout{
protectedTextViewcontentView;
protectedImageViewexpandView;
protectedinttextColor;
protectedfloattextSize;
protectedintmaxLine;
protectedStringtext;
publicintdefaultTextColor=Color.BLACK;//默认文字颜色
publicintdefaultTextSize=12;//默认文字大小
publicintdefaultLine=3;//默认行数
publicTextMoreTextView(Contextcontext,AttributeSetattrs){
super(context,attrs);
initalize();
initWithAttrs(context,attrs);
//bindListener();
}
protectedvoidinitWithAttrs(Contextcontext,AttributeSetattrs){
TypedArraya=context.obtainStyledAttributes(attrs,
R.styleable.MoreTextStyle);
inttextColor=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();
}
protectedvoidinitalize(){
setOrientation(VERTICAL);
setGravity(Gravity.RIGHT);
contentView=newTextView(getContext());
addView(contentView,LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT);
expandView=newImageView(getContext());
intpadding=dip2px(getContext(),5);
expandView.setPadding(padding,padding,padding,padding);
expandView.setImageResource(R.drawable.ic_expand_more_red_700_24dp);
LayoutParamsllp=newLayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
addView(expandView,llp);
}
protectedvoidbindTextView(intcolor,floatsize,finalintline,Stringtext){
contentView.setTextColor(color);
contentView.setTextSize(TypedValue.COMPLEX_UNIT_PX,size);
contentView.setText(text);
ViewTreeObserverobserver=contentView.getViewTreeObserver();
observer.addOnGlobalLayoutListener(newViewTreeObserver.OnGlobalLayoutListener(){
//判断写在这个方法里面能拿到contentView.getLineCount(),否则返回时0;
@Override
publicvoidonGlobalLayout(){
ViewTreeObserverobs=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(newRunnable(){
@Override
publicvoidrun(){
expandView.setVisibility(contentView.getLineCount()>line?View.VISIBLE:View.GONE);
//Log.e("aaa","run:"+contentView.getLineCount());
}
});
}
protectedvoidbindListener(){
setOnClickListener(newOnClickListener(){
booleanisExpand;
@Override
publicvoidonClick(Viewv){
isExpand=!isExpand;
contentView.clearAnimation();
finalintdeltaValue;
finalintstartValue=contentView.getHeight();
intdurationMillis=350;
if(isExpand){
deltaValue=contentView.getLineHeight()*contentView.getLineCount()-startValue;
RotateAnimationanimation=newRotateAnimation(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;
RotateAnimationanimation=newRotateAnimation(180,0,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
animation.setDuration(durationMillis);
animation.setFillAfter(true);
expandView.startAnimation(animation);
}
Animationanimation=newAnimation(){
protectedvoidapplyTransformation(floatinterpolatedTime,Transformationt){
contentView.setHeight((int)(startValue+deltaValue*interpolatedTime));
}
};
animation.setDuration(durationMillis);
contentView.startAnimation(animation);
}
});
}
publicTextViewgetTextView(){
returncontentView;
}
publicvoidsetText(CharSequencecharSequence){
contentView.setText(charSequence);
}
publicstaticintdip2px(Contextcontext,floatdipValue){
finalfloatscale=context.getResources().getDisplayMetrics().density;
return(int)(dipValue*scale+0.5f);
}
}
这个类这样就写好了。调用直接在布局文件中引用就行了。
源码下载:http://xiazai.jb51.net/201610/yuanma/Androidtextview(jb51.net).rar
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。