点击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);