今天面试遇到的一个问题,Android TextView点击实现展开带动画效果(即文字一行一行向下展出来),不过这个是不带Animation的,晚上自己回家没事就实现了下。
下面说下思路吧,就是先获取TextView完全展开时的最大maxLines记录下来,让后再把TextView的maxLine设置为你想指定的任何值,我这里指定的是1,这样加载完成VIew之后我们看到的TextView就不是完全展开的,这样做的主要目的是拿到完全展开的maxLines,让后用户点击的时候不断的更新maxLine大小即可。
至于如何在onCreate里面捕获到最大的maxLines,我们可以这样做,用View类中的getViewTreeObserver方法,可以获取到指定View的观察者,在绘制控件前的一刹那进行回调,这样速度上又不耽误,得到的数据又是准确的,但此方法在之后可能会被反复调用,因此需要加入限制,普通需求下,只用View类中的getViewTreeObserver方法,可以获取到指定View的观察者,在绘制控件前的一刹那进行回调,这样速度上又不耽误,得到的数据由是准确的,但此方法在之后可能会被反复调用,因此需要加入限制,普通需求下,只计算一次就够了计算一次就够了。
具体实现请看代码吧,代码上面都有注释我就不一一解释了。
主界面MainActivity.java:
package cn.mytest.expandtextview;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnPreDrawListener;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener{
private static final int MAX = 1;//初始maxLine大小
private static final int TIME = 20;//间隔时间
private int maxLines;
private TextView textView;
private boolean hasMesure = false;
private Thread thread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView(){
//获取ViewTreeObserver View观察者,并注册一个监听事件,这个时间是在View还未绘制的时候执行的,也就是在onDraw之前
//textView默认是没有maxLine限制的,这样我就可以计算到完全显示的maxLine
textView = (TextView) findViewById(R.id.textView);
ViewTreeObserver viewTreeObserver = textView.getViewTreeObserver();
viewTreeObserver.addOnPreDrawListener(new OnPreDrawListener() {
@Override
public boolean onPreDraw() {
//只需要获取一次就可以了
if(!hasMesure){
//这里获取到完全展示的maxLine
maxLines = textView.getLineCount();
//设置maxLine的默认值,这样用户看到View就是限制了maxLine的TextView
textView.setMaxLines(MAX);
hasMesure = true;
}
return true;
}
});
textView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
toggle();
}
/**
* 打开TextView方法
*/
@SuppressLint("HandlerLeak")
private void toggle(){
final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int lines = msg.what;
//这里接受到消息,让后更新TextView设置他的maxLine就行了
textView.setMaxLines(lines);
textView.postInvalidate();
}
};
if(thread != null)
handler.removeCallbacks(thread);
thread = new Thread(){
@Override
public void run() {
int count = MAX;
while(count++ <= maxLines){
//每隔20mms发送消息
Message message = new Message();
message.what = count;
handler.sendMessage(message);
try {
Thread.sleep(TIME);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
super.run();
}
};
thread.start();
}
}
简单布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:text="@string/test"
android:textSize="18sp" />
</RelativeLayout>
string.xml文本:
<string name="test">1996年1月,身为加州斯坦福大学理学博士生的拉里·佩奇和谢尔盖·布卢姆在学校开始一项关于搜索的研究项目。[26] 区别于传统的搜索靠搜索字眼在页面中出现次数来进行结果排序的方法,两人开发了一个对网站之间的关系做精确分析的搜寻引擎。[27] 这个名为PageRank的引擎通过检查网页中的反向链接以评估站点的重要性,此引擎的精确度胜于当时的基本搜索技术。[28][29] 最初,佩奇和布卢姆将这个搜索引擎命名为‘BackRub’,直到后来改为‘Google’。[30][31][32] 这个新名字来源于一个数学大数googol(数字1后有100个0,即自然数10100)单词错误的拼写方式,[33][34] 象征着为人们提供搜索海量优质信息的决心。[35] Google搜索引擎在斯坦福大学的网站上启用,域名为google.stanford.edu。[36]</string>