最近做项目,效果图要用到TextView的折叠,超过一定行数的时候,就会折叠起来,点击可以展开。网上找了一些效果,自己也稍作了修改。便拿来与网友分享分享。
参考文献:http://www.jb51.net/article/95544.htm
第一种:通过多个布局组合实现
大概步骤:
- 定义布局,垂直的线性LinearLayout布局、TextView和ImageView。 在layout中定义基本组件。
- 设置TextView的高度为指定行数*行高。 不使用maxLine的原因是maxLine会控制显示文本的行数,不方便后边使用动画展开全部内容。因此这里TextView的高度也因该为wrap_content。
- 给整个布局添加点击事件,绑定动画。 点击时,若TextView未展开则展开至其实际高度,imageView 旋转;否则回缩至 指定行数*行高 , imageView 旋转缩回。
布局文件:
<"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); } }
第二种方法,如果用的地方多可以省去很多冗余代码:具体步骤就不直接分析。
核心代码:
<"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); } }
这个类这样就写好了。调用直接在布局文件中引用就行了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持查字典教程网。