Android--RecycleView点击条目的展开收缩

点击RecycleView条目展开收缩

原文链接:https://blog.csdn.net/weixin_34211761/article/details/87305545

1.可展开收起的TextView

public class ExpandTextView extends AppCompatTextView{
    /**
     * true 展开 false 收起
     */
    boolean mExpanded;
    /**
     * 返回状态
     */
    Callback mCallback;
    /**
     * 原文字内容
     */
    String mText;
    /**
     * 最多展示的行数
     */
    final int maxLineCount = 3;
    /**
     * 省略文字
     */
    final String ellipsizeText = "... 展开";
    final String expandsizeText = "收缩";

    public ExpandTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //文字计算辅助工具
        StaticLayout s1 = new StaticLayout(mText,getPaint(),getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
                Layout.Alignment.ALIGN_CENTER,1,0,true);

        //计算行数
        int lineCount = s1.getLineCount();
        if(lineCount > maxLineCount){
            if(mExpanded){
                String newText = mText+expandsizeText;
                SpannableStringBuilder stringBuilder=new SpannableStringBuilder(newText);
                stringBuilder.setSpan(new ForegroundColorSpan(Color.parseColor("#FF971B")),newText.length()-expandsizeText.length(),newText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                setText(stringBuilder);
                mCallback.onExpand();
            }else {
                lineCount = maxLineCount;
                //省略文字的宽度
                float dotWith = getPaint().measureText(ellipsizeText);
                //找出第showlinecount行的文字
                int start = s1.getLineStart(lineCount -1);
                int end = s1.getLineEnd(lineCount -1);
                String lineText = mText.substring(start,end);

                //将第showlinecount行最后的文字替换成ellipsizeText
                int endIndex = 0;
                for(int i= lineText.length() -1; i >= 0;i--){
                    String str = lineText.substring(i,lineText.length());
                    //找出文字宽度大于ellipsizeText的字符
                    if(getPaint().measureText(str) >=dotWith){
                        endIndex = i;
                        break;
                    }
                }

                //新的第showLineCount的文字
                String newEndLineText = lineText.substring(0,endIndex) +ellipsizeText;
                SpannableString spannableString = new SpannableString(mText.substring(0,start) + newEndLineText);
                spannableString.setSpan(new ForegroundColorSpan(Color.parseColor("#FF971B")), mText.substring(0,end).length(),(mText.substring(0,start) + newEndLineText).length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                //最终显示的文字
//                setText(mText.substring(0,start) + newEndLineText);
                setText(spannableString);
                mCallback.onCollapse();
            }
        }else{
            setText(mText);
            mCallback.onLoss();
        }
        //重新计算高度
        int lineHeight = 0;
        for(int i = 0;i < lineCount;i++){
            Rect lineBound = new Rect();
            s1.getLineBounds(i,lineBound);
            lineHeight +=lineBound.height();
        }
        lineHeight += getPaddingTop() + getPaddingBottom();
        setMeasuredDimension(getMeasuredWidth(),lineHeight);
    }
    /**
     * 设置要显示的文字以及状态
     * @param text
     * @param expanded true:展开,false:收起
     * @param callback
     */
    public void setText(String text, boolean expanded, Callback callback) {
        mText = text;
        mExpanded = expanded;
        mCallback = callback;

        // 设置要显示的文字,这一行必须要,否则 onMeasure 宽度测量不正确
        setText(text);
    }

    /**
     * 展开收起状态变化
     * @param expanded
     */
    public void setChanged(boolean expanded) {
        mExpanded = expanded;
        requestLayout();
    }
    /**
     * 结果回调
     */
    public interface Callback{
        /**
         * 展开状态
         */
        void onExpand();

        /**
         * 收起状态
         */
        void onCollapse();

        /**
         * 行数小于最小行数,不满足展开或这是收起条件
         */
        void onLoss();
    }

}

二.引入布局文件

1.在Activity的xml文件中引入RecycleView

<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/recycle_view_item"/>

 2.Adapter的item的xml文件

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:cardCornerRadius="@dimen/space_14"
    app:cardElevation="@dimen/space_4"
   android:layout_margin="@dimen/space_10"
    android:background="@color/transparent">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#33ff0000"
        android:padding="@dimen/space_10">
    <ImageView
        android:id="@+id/recycle_iv_icon"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="10dp"
        android:src="@mipmap/ic_launcher"/>
        <com.hjq.demo.widget.ExpandTextView
            android:id="@+id/recycle_tv_message"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:layout_centerVertical="true"
            android:layout_toRightOf="@id/recycle_iv_icon"
            android:layout_toLeftOf="@id/recycle_icon"
            android:text="让我们成为好友吧?" />
        <ImageView
            android:id="@+id/recycle_icon"
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_centerVertical="true"
            android:layout_marginLeft="2dp"
            android:layout_alignParentRight="true"
            android:src="@mipmap/ic_launcher"/>
    </RelativeLayout>
</android.support.v7.widget.CardView>

 

 三.适配器的引用

public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private List<Data> itemDataList;

    public MyAdapter(List<Data> dataList) {
        this.itemDataList = dataList;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        return new ViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.itemfour, viewGroup, false));
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
        final ViewHolder viewH = (ViewHolder) viewHolder;
        final Data data = itemDataList.get(i);
        viewH.tv_message.setText(itemDataList.get(i).getProduct(), itemDataList.get(i).isExpanded(), new ExpandTextView.Callback() {
            @Override
            public void onExpand() {
                // 展开状态,比如:显示“收起”按钮
            }

            @Override
            public void onCollapse() {
                // 收缩状态,比如:显示“全文”按钮
            }

            @Override
            public void onLoss() {
                // 不满足展开的条件,比如:隐藏“全文”按钮
            }
        });
        viewH.recycle_icon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 保存当前行的状态
                data.setExpanded(!data.isExpanded());
                // 切换状态
                viewH.tv_message.setChanged(data.isExpanded());
            }
        });
    }


    @Override
    public int getItemCount() {
        return itemDataList.size();
    }

    class ViewHolder extends RecyclerView.ViewHolder {

        ImageView img_icon,recycle_icon;
        ExpandTextView tv_message;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            img_icon = itemView.findViewById(R.id.recycle_iv_icon);
            recycle_icon = itemView.findViewById(R.id.recycle_icon);
            tv_message = itemView.findViewById(R.id.recycle_tv_message);
        }
    }
}

四.创建的bean

public class Data implements Serializable {

    private String product;
    private boolean expanded;

    public String getProduct() {
        return product;
    }

    public void setProduct(String product) {
        this.product = product;
    }

    public boolean isExpanded() {
        return expanded;
    }

    public void setExpanded(boolean expanded) {
        this.expanded = expanded;
    }

    public Data(String product) {
        this.product = product;
    }
}

五.MainActivity的使用

RecyclerView view=findViewById(R.id.recycle_view_item);
view.setLayoutManager(new LinearLayoutManager(getContext(),LinearLayoutManager.VERTICAL,false));
List<Data> list=new ArrayList<>();
Data data1=new Data("培训课程 -> lambda表达式与集合一起使用,是最常见的场景,可以各种筛选、映射、变换操作符和对集合数据进行各种操作,非常灵活,相信使用过RxJava中的开发者已经体会到这种快感,没错Kotlin在语言层面,无需增加额外库,就给你提供了支持函数式编程API。");
list.add(data1);

Data data2=new Data("培训课程 ->我们试想一个场景就是可能会用到多个lambda表达式,但是这些lambda表达式的类型很多相同,我们就很容易把所有相同一大串的Lambda类型重复声明或者你的lambda类型声明太长不利于阅读。实际上不需要,对于Kotlin这门反对一切啰嗦语法的语言来说,它都给你提供一系列的解决办法,让你简化代码的同时又不降低代码的可读性。\n");
list.add(data2);

MyAdapter myAdapter = new MyAdapter(list);
view.setAdapter(myAdapter);

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值