App中有一个类似于朋友圈文章的全文显示与收起的功能,研究了前辈的代码,分享给大家。
唯一的难点在于如何在布局完成之前获得文字的实际行数, 主要方法为view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
在视图树将要绘制的时候提供一个监听,此时视图树已经测量完毕,并且有了布局框架,在这里我们可以在绘制之前得到控件的测量数据,并且修改影响最后的绘制结果。然后我们根据实际行数与需求行数的大小关系来判断文字的显示与折叠,说完了,直接上代码。
布局文件:
<?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="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tv_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
android:background="@drawable/selector_background_textview"
android:padding="25dp"
android:text="全文"
android:textColor="@android:color/holo_red_dark" />
</LinearLayout>
功能代码:
//lineCount文字的行数
//fold是否是折叠状态
//defaultMaxLine默认最多展示的行数
tvAll.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (lineCount > defaultMaxLine) {
if (fold) {
tvContent.setMaxLines(10086);
tvAll.setText("收起");
} else {
tvContent.setMaxLines(defaultMaxLine);
tvAll.setText("全文");
}
fold = !fold;
}
}
});
tvContent.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
//这个回调会调用多次,获取完行数记得注销监听
tvContent.getViewTreeObserver().removeOnPreDrawListener(this);
lineCount = tvContent.getLineCount();
if (lineCount > defaultMaxLine) {
tvContent.setMaxLines(defaultMaxLine);
fold = true;
tvAll.setVisibility(View.VISIBLE);
tvAll.setText("全文");
} else {
tvAll.setVisibility(View.GONE);
}
return true;
}
});
源码:
/**
* Interface definition for a callback to be invoked when the view tree is about to be drawn.
*/
public interface OnPreDrawListener {
/**
* Callback method to be invoked when the view tree is about to be drawn. At this point, all
* views in the tree have been measured and given a frame. Clients can use this to adjust
* their scroll bounds or even to request a new layout before drawing occurs.
*
* @return Return true to proceed with the current drawing pass, or false to cancel.
*
* @see android.view.View#onMeasure
* @see android.view.View#onLayout
* @see android.view.View#onDraw
*/
public boolean onPreDraw();
}