可折叠展开的TextView -- ExpandableTextView

可折叠展开的TextView

在很多时候需要用到可以折叠、展开的TextView,最常见的就是在各大应用市场描述APP的时候,因为有的描述内容太长了,所以只显示了几行,当点击之后就展开显示了全部内容,再次点击又可以折叠起来。今天我们就从几个不同的角度来实现这种功能,当然越简单的方法效果也就越low了。

通过设置可见与不可见来实现

其实这种方法也最容易想到的,就是在布局的时候就设置两个TextView,其中一个TextView通过

android:maxLines="Integer"

来设置只显示几行,另外一个则按照常规的设置显示全部,只是一开始设置

android:visibility="gone"

那么通过切换这两个TextView的显示与隐藏,就可以达到类似折叠展开的效果了。只是看上去没有任何动画,显得很死板,效果自然不怎么好了。

通过动态改变TextView的高度

其实从另外一个角度来看,这种TextView的折叠与展开就是控件本身高度的一个逐渐变化。
那么一开始就设置一个限制的高度,可能很多人会想通过以下连个个属性来限制TextView的高度

android:maxLines="Integer"
android:maxHeight="Integer"

但是设置了这两个中的任何一个属性之后,再要改变TextView的高度是没有任何效果的。
那么就有人会问了,该怎么设置TextView一开始的高度呢?第一种方法是直接设置TextView的高度,将其设置为一个固定的值,但是在改变了字体大小的时候,那么也要跟着改变这个值,而且不知道设置多少比较合适。第二种方法就是动态获取一个高度:

TextView textView = new TextView(this);
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);//设置字体大小14dp
textView.setMaxLines(3);
textView.setLines(3);// 强制有3行
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.AT_MOST);
textView.measure(widthMeasureSpec, heightMeasureSpec);
return textView.getMeasuredHeight();

以上代码,通过创建一个TextView,并给它设置字体大小,以及限制显示的行数,再用measure()方法测量获取到高度。
可能有的人不太理解measure()的使用。在自定义View的时候,经常看见onMeasure()这个方法,可以将其理解为制定测量的规则,而这里使用的measure()算是对控件的实际测量。
在获取到被限制的高度之后,就在一开始初始化控件的时候,给TextView设置上这么一个高度

LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) text1.getLayoutParams();
layoutParams.height=value;      // 设置初始化时候的高度
text1.setLayoutParams(layoutParams);

随后再获取完整显示时候的高度了。

int width = text1.getMeasuredWidth();  //  由于宽度不会发生变化  宽度的值取出来
text1.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;//  让高度包裹内容

//    参数1  测量控件mode    参数2  大小
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);  //  mode+size
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.AT_MOST);// 我的高度 最大是1000
// 测量规则 宽度是一个精确的值width, 高度最大是1000,以实际为准
text1.measure(widthMeasureSpec, heightMeasureSpec); // 通过该方法重新测量控件

return text1.getMeasuredHeight();

在获取完这两个高度的值以后,就可以设置一个动画效果,让高度从小的那个值逐渐增加到大的那个值。这里我们就直接采用值动画了,至于为什么就自己琢磨吧。

ValueAnimator animator=ValueAnimator.ofInt(startHeight,targetHeight);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        int value=(Integer) animation.getAnimatedValue();
        ayoutParams.height=value;
        text1.setLayoutParams(layoutParams);
    }
});

通过自定义控件

一般在使用可折叠展开的TextView的时候,都会有一个用来指示的小箭头(ImageView)在TextView的下面。那么我们就可以将TextView和ImageView结合起来,通过自定义的LinearLayout来控制。
1、我们将LinearLayout设置为垂直布局,因为使用场景大部分都是垂直的。

setOrientation(LinearLayout.VERTICAL);

2、初始化控件

@Override
protected void onFinishInflate() {
    // 初始化TextView并设置点击事件
    mTv = (TextView) findViewById(R.id.expandable_text);
    mTv.setOnClickListener(this);
    // 初始化小箭头,并设置图片和点击事件
    mButton = (ImageButton) findViewById(R.id.expand_collapse);
    mButton.setImageDrawable(mCollapsed ? mExpandDrawable : mCollapseDrawable);
    mButton.setOnClickListener(this);
}

3、给TextView设置文本内容
4、获取TextView的真正高度

private static int getRealTextViewHeight(@NonNull TextView textView) {
    int textHeight = textView.getLayout().getLineTop(textView.getLineCount());
    int padding = textView.getCompoundPaddingTop() + textView.getCompoundPaddingBottom();
    return textHeight + padding;
}

5、重写onMeasure()方法,根据不同的状态给TextView设置不同的高度
6、写onClick()点击事件,点击后播放动画。

由于这种方法是参考一个第三库来的,所以写得很简单,具体的代码可以在此下载
[ExpandableTextView](https://github.com/whyalwaysmea/ExpandableTextView)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值