长文案展开和收缩实现

前言

Android应用中通常有一些很长的文案,比如有些用户评论或者文章内容特别的长,如果整体都展示出来可能会占据很大的空间,其他的控件都无法完全展现在用户面前。通常程序会对长文案做收缩操作,只展示开头的部分,用户如果真的对内容感兴趣可以点击展开按钮或文字,这种功能在应用中很常见。现在就来简单实现两种常见的展开缩放功能。

实现效果

这里写图片描述

自定义控件实现

自定义控件实现要求展开/缩放按钮和长文案TextView是分开的空间,通常可以用LinearLayout作为整体的布局,TextView放在最前方,按钮可以放在最右边或者最下方,用户点击按钮会修改TextView的android:maxLines属性,打开时androi:maxLines为Integer.MAX_VALUE,文案缩起来时设置为最小展示行数。

public class ExpandableTextView extends LinearLayout {
    private TextView mText;
    private ImageView mArrow;
    private boolean mIsExpanded = true;

    public ExpandableTextView(Context context) {
        this(context, null);
    }

    public ExpandableTextView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ExpandableTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        setOrientation(LinearLayout.VERTICAL);
        mText = new TextView(getContext());
        LinearLayout.LayoutParams params = new LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        mText.setText(R.string.long_text);
        mText.setMaxLines(3);
        mText.setEllipsize(TextUtils.TruncateAt.END);
        addView(mText, params);

        mArrow = new ImageView(getContext());
        mArrow.setImageResource(R.drawable.ic_arrow_downward);
        LinearLayout.LayoutParams arrowParams = new LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        arrowParams.gravity = Gravity.CENTER_HORIZONTAL;
        addView(mArrow, arrowParams);
        mArrow.setOnClickListener(view -> {
            // 如果当前文案处于展开状态,设置最大行数为3
            // 收缩文案到3行状态
            if (mIsExpanded) {
                mText.setMaxLines(3);
                mText.setEllipsize(TextUtils.TruncateAt.END);
                mArrow.setImageResource(R.drawable.ic_arrow_downward);
            } else {
                // 如果当前文案处于收缩状态,将文案展开
                mText.setMaxLines(Integer.MAX_VALUE);
                mArrow.setImageResource(R.drawable.ic_arrow_upward);
            }

            mIsExpanded = !mIsExpanded;
        });
    }
}

ClickSpan实现

Android中有SpannableString可以为文本添加各种效果,如果需要在文案的最后添加展开/收缩文字,就需要使用ClickSpan功能。Android的TextUtils工具类提供了一个根据长度来获取压缩字符串的方法,压缩字符串是将”查看更多“添加到压缩字符串后面,并且为它添加点击事件。展开文案后在后面添加“收起查看”文案并且也为它添加收起的ClicKSpan事件。

public class TextViewActivity extends AppCompatActivity {
    // 展示文案textView
    private TextView textView;
    // 压缩是展示的文案
    private SpannableString collapsedString;
    // 展开式展示的文案
    private SpannableString expandedString;
    // 是否处于展开状态
    private boolean expanded = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_text_view);
        textView = (TextView) findViewById(R.id.text);
        // 初始化压缩和展示文案
        textView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
            if (expandedString == null) {
                // 为原始全部文案添加“收起查看<<”并为这6个字符设置点击事件
                String text = textView.getText().toString();
                String alltext = text + "收起查看<<";
                expandedString = new SpannableString(alltext);
                expandedString.setSpan(new TextClickSpan(textView), alltext.length() - 6, alltext.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

                // 计算当展示2.5行宽度的文案时压缩文案
                String ellipse = TextUtils.ellipsize(text, textView.getPaint(), 2.5f * textView.getWidth(), TextUtils.TruncateAt.END).toString();

                // 为压缩文案添加“查看更多>>”并且设置点击事件
                String result = ellipse + "查看更多>>";
                collapsedString = new SpannableString(result);
                collapsedString.setSpan(new TextClickSpan(textView), result.length() - 6, result.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
                textView.setMovementMethod(LinkMovementMethod.getInstance());
                textView.setHighlightColor(Color.parseColor("#36969696"));
                textView.setText(collapsedString);
            }
        });
    }

    private class TextClickSpan extends ClickableSpan {
        private TextView textView;

        public TextClickSpan(TextView textView) {
            this.textView = textView;
        }

        @Override
        public void onClick(View widget) {
            // 如果在文案展开情况下点击就展示压缩文案,否则展示全部文案
            if (expanded) {
                textView.setText(collapsedString);
            } else {
                textView.setText(expandedString);
            }
            expanded = !expanded;
        }
    }
}

长文案展开和收缩实现起来还是比较简单的,不过作为一个常用的功能还是值得记录一下。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值