显示与隐藏本质是:
隐藏状态下TextView的高度和展开状态下TextView高度的切换。所以这个问题的关键是如何得到两种状态TextView的高度:
step1:
在Framlayout下放置两个TextView,一个用于显示一个用于计算展开状态下的TextView的高度。
<FrameLayout
android:id="@+id/fl_survey"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_survey"
style="@style/sty_project_tab_content" />
<TextView
android:id="@+id/tv_survey_back"
style="@style/sty_project_tab_content" />
</FrameLayout>
<style name="sty_project_tab_content_back">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">@dimen/project_detail_fs_tab_content</item>
<item name="android:textColor">@color/app_font_light</item>
<item name="android:paddingLeft">@dimen/app_padding_left</item>
<item name="android:paddingRight">@dimen/app_padding_right</item>
<item name="android:paddingBottom">@dimen/base_padding_20</item>
<item name="android:background">@color/app_content_bg</item>
<item name="android:visibility">gone</item>
</style>
<style name="sty_project_tab_content"
parent="@style/sty_project_tab_content_back">
<item name="android:maxLines">2</item>
<item name="android:ellipsize">end</item>
<item name="android:visibility">visible</item>
</style>
step2
建立一个内部类(当然也可以是其它方式)用来表示展开与隐藏状态下的高度
private class TextViewHeightInfo{
private int normalHeight;//默认显示的高度
private int expandHeight;//展开后的高度
public int getNormalHeight() {
return normalHeight;
}
public void setNormalHeight(int normalHeight) {
this.normalHeight = normalHeight;
}
public int getExpandHeight() {
return expandHeight;
}
public void setExpandHeight(int expandHeight) {
this.expandHeight = expandHeight;
}
}
step3
建立一个集合存储要操作的TextView与TextViewHeightInfo信息
private HashMap<TextView,TextViewHeightInfo> tvMaps;
step4
通过以下方法去计算存储展开与隐藏状态下TextView的高度信息
/**
* 根据文字的行数自动确定其原始高度和实际高度的大小,并保存
* @param ivArrow 箭头对象,当隐藏状态下能全部展示内容时,箭头应该不用展示
* @param textView 隐藏状态下的TextView,也是真实操作的TextView
* @param textViewBack 占位TextView,主要用于计算展开式TextView的高度
* @param content 要显示的内容
*/
private void calculateTvHeightInfo(final ImageView ivArrow,
final TextView textView,
final TextView textViewBack,
String content)
{
textView.setText(content);
ViewTreeObserver vto = textView.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
tvMaps.get(textView).setNormalHeight(textView.getHeight());
textView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
textViewBack.setText(content);
ViewTreeObserver vtoBack = textViewBack.getViewTreeObserver();
vtoBack.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
tvMaps.get(textView).setExpandHeight(textViewBack.getHeight());
textViewBack.getViewTreeObserver().removeGlobalOnLayoutListener(this);
textViewBack.setVisibility(View.GONE);
int norH = tvMaps.get(textView).getNormalHeight();
int ExpH = tvMaps.get(textView).getExpandHeight();
if(norH >= ExpH){
//无需展开
ivArrow.setVisibility(View.GONE);
}else{
ivArrow.setVisibility(View.VISIBLE);
}
}
});
}
step5
点击箭头的事件封装,这里是单纯的改变高度,在这里完全可以加入属性动画已达到更炫酷的效果
/**
* 点击箭头自动修改其高度已实现全部展示还是只展示初始高度
* @param ivArrow 箭头
* @param changedTv 要改变高度的TextView
*/
private void onClickArrow(ImageView ivArrow,TextView changedTv){
int normalHeight = tvMaps.get(changedTv).getNormalHeight();
int expandHeight = tvMaps.get(changedTv).getExpandHeight();
if(expandHeight > normalHeight){
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) changedTv.getLayoutParams();
boolean expandSurvey = (boolean) changedTv.getTag();
if(expandSurvey){
params.height = normalHeight;
changedTv.setTag(false);
changedTv.setMaxLines(2);
ivArrow.setImageResource(R.drawable.xiangxia);
}else{
params.height = expandHeight;
changedTv.setMaxLines(Integer.MAX_VALUE);
changedTv.setTag(true);
ivArrow.setImageResource(R.drawable.xiangshang);
}
changedTv.setLayoutParams(params);
}
}