还是先描述一下需求,这个在其余的app中应该也经常看见,就是当一个段文字很长的时候,我们往往为了展示的时候节约展示的空间,需要将我们的文字折叠起来,如果用户想看里面的详细内容话,则需要用户去点击一下改控件,然后TextView展开,显示全部的内容。由于我在本次的项目中有这个需求,所以我将其独立成了一个自定义控件,方便在以后的开发中能直接使用。下面是效果图
先来说说大致思路,其实也是很简单的一个控件,首先该控件是继承LinearLayout的,其中的布局文件包括一个TextView和一个下拉三角的ImageView,当用户在单击这个LinearLayout的时候,我会开一个子线程,让改线程睡20ms,睡完后再向主线程中发送一个handler,在主线程中重新设置一下TextView的显示行数,一次循环,直到显示全部内容为止,在折叠起来的时候设计思路也是一样的,当然在该控件中我用了一个isExp来标记该控件是否展开是否折叠。好了,大致的设计思路就是这样,很简单,接下来贴代码了,可以复制粘贴后直接使用
下面是布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical" >
<TextView
android:id="@+id/tvFold"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lineSpacingExtra="5dp"
android:textColor="#666666"
android:textSize="14sp" />
<ImageView
android:id="@+id/ivFold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:src="@drawable/company_desc_expansion_icon"
android:visibility="gone" />
</LinearLayout>
下面是页面处理的逻辑代码
package com.renrui.job.widget;
import com.renrui.job.R;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
/**
* 可折叠的TextView
*/
public class FoldTextView extends LinearLayout
{
FoldTextViewHolder mFoldTextViewHolder;
View myView;
/**
* 真实行数
*/
int realLineCounts = 0;
/**
* 默认行数
*/
int defaultLineCounts = 4;
/**
* 真实高度
*/
int realHeight = 0;
/**
* 折叠后的高度
*/
int foldHeight = 0;
boolean isFirstLoad = true;
/**
* Icon状态 展开动画
*/
RotateAnimation expIconAnimation;
/**
* Icon状态 折叠动画
*/
RotateAnimation foldIconAnimation;
/**
* 当前是否展开
*/
boolean isExp = false;
/**
* 展开TextView
*/
final int TEXT_OPEN = 1;
/**
* 关闭TextView
*/
final int TEXT_CLOSE = 2;
Handler mHander = new Handler()
{
LayoutParams layoutParma;
public void handleMessage(android.os.Message msg)
{
int lines = (Integer) msg.obj;
switch (msg.what)
{
case TEXT_OPEN: //打开,增加高度
mFoldTextViewHolder.tvFold.setMaxLines(lines);
break;
case TEXT_CLOSE://关闭,减少高度
mFoldTextViewHolder.tvFold.setMaxLines(lines);
break;
}
};
};
public FoldTextView(Context context)
{
super(context);
init();
}
public FoldTextView(Context context, AttributeSet attrs)
{
super(context, attrs);
init();
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public FoldTextView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
init();
}
private void init()
{
LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
myView = inflater.inflate(R.layout.view_widget_foldtextview, null);
this.addView(myView, layoutParams);
//设置小箭头展开时的旋转动画
expIconAnimation = new RotateAnimation(0f, 180f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
expIconAnimation.setDuration(300);
expIconAnimation.setFillAfter(true);
//设置小箭头关闭时的旋转动画
foldIconAnimation = new RotateAnimation(180f, 0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
foldIconAnimation.setDuration(300);
foldIconAnimation.setFillAfter(true);
mFoldTextViewHolder = new FoldTextViewHolder(this);
}
public void setText(String text)
{
mFoldTextViewHolder.tvFold.setText(text);
ViewTreeObserver vto = mFoldTextViewHolder.tvFold.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
@Override
public void onGlobalLayout()
{
if (!isFirstLoad)
{
return;
}
//获取真实行数
realLineCounts = mFoldTextViewHolder.tvFold.getLineCount();
realHeight = mFoldTextViewHolder.tvFold.getMeasuredHeight();
//如果真实行数大于默认的显示行数,则默认将其折叠起来 isExp为false
if (realLineCounts > defaultLineCounts)
{
mFoldTextViewHolder.tvFold.setMaxLines(defaultLineCounts);
mFoldTextViewHolder.tvFold.measure(0, 0);
foldHeight = mFoldTextViewHolder.tvFold.getMeasuredHeight();
mFoldTextViewHolder.ivFold.setVisibility(View.VISIBLE);
mFoldTextViewHolder.tvFold.setOnClickListener(FoldOnclick);
mFoldTextViewHolder.ivFold.setOnClickListener(FoldOnclick);
isExp = false;
}
//如果真实行数小于默认行数,则直接展示出来。isExp为true;
else
{
mFoldTextViewHolder.ivFold.setVisibility(View.GONE);
isExp = true;
}
isFirstLoad = false;
}
});
}
View.OnClickListener FoldOnclick = new OnClickListener()
{
@Override
public void onClick(View v)
{
if (isExp)
{
new Thread(new Runnable()
{
@Override
public void run()
{
int endcount = realLineCounts;
while(endcount-- > defaultLineCounts){
Message msg = Message.obtain();
msg.what = TEXT_CLOSE;
msg.obj = endcount;
mHander.sendMessage(msg);
try
{
Thread.sleep(20);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}).start();
mFoldTextViewHolder.ivFold.setAnimation(foldIconAnimation);
foldIconAnimation.startNow();
isExp = false;
} else
{
new Thread(new Runnable()
{
@Override
public void run()
{
int startcount = defaultLineCounts;
while(startcount++ < realLineCounts){
Message msg = Message.obtain();
msg.what = TEXT_OPEN;
msg.obj = startcount;
mHander.sendMessage(msg);
try
{
Thread.sleep(20);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}).start();
mFoldTextViewHolder.ivFold.setAnimation(expIconAnimation);
expIconAnimation.startNow();
isExp = true;
}
}
};
static class FoldTextViewHolder
{
TextView tvFold;
ImageView ivFold;
public FoldTextViewHolder(View v)
{
tvFold = (TextView) v.findViewById(R.id.tvFold);
ivFold = (ImageView) v.findViewById(R.id.ivFold);
}
}
}
好了 以上就是该控件的全部代码了,不多,但是有时候还是挺好用的