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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。