点击RecycleView条目展开收缩
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);