最近工作中需要使用到ExpandTextview,因为没有原生的控件可以使用,GitHub上面有没有找到合适的,那就自己造一个轮子吧:)
最终要实现的效果就是TextView的行数最大不超过两行,大于两行的会有下拉按钮可以让用户展开或者收缩内容,如果本来的内容就在两行以下的,就隐藏下拉按钮,行数保持原有的样子。最后我们希望达到的效果是这样的:
内容超过两行可以收缩或者展开,内容没有超过两行的则保持不变。
因为我的实际需求是要在列表中展示内容,那么就先来创建一个列表:
- activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycleView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
- item_expand.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/view_item_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv_item_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:padding="10dp"
android:text="我是内容"
android:textColor="@android:color/black" />
<ImageView
android:id="@+id/iv_item_arrow"
android:layout_width="wrap_content"
android:layout_gravity="right"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
android:src="@drawable/arrow_down" />
</LinearLayout>
</LinearLayout>
布局完成了之后,那么接下来我们的主要关注点就是adapter里面的实现了,自定义一个CustomAdapter,并在binding方法中实现我们的逻辑代码:
package com.lxy.mew.expandtextview.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.lxy.mew.expandtextview.R;
import java.util.ArrayList;
import java.util.List;
/**
*
* Created by master on 2017/4/29.
*/
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder>
{
private Context context;
private List<String> datas = new ArrayList<>();
public CustomAdapter(Context context)
{
this.context = context;
}
public void setDatas(List<String> datas)
{
this.datas = datas;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
return new ViewHolder(LayoutInflater.from(context).inflate(R.layout.item_expand, parent, false));
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position)
{
String item = datas.get(position);
holder.tvContent.setText(item);
final View.OnClickListener listener = new View.OnClickListener()
{
boolean isExpand;//设置是否展开的标记
@Override
public void onClick(View v)
{
if (isExpand)
{
holder.tvContent.setMaxLines(2);//如果当前是展开的,则设置为闭合
holder.ivArrow.setRotation(0);//箭头重置为向下的状态
isExpand = false;
} else
{
holder.tvContent.setMaxLines(Integer.MAX_VALUE);//如果是闭合的,则展开
holder.ivArrow.setRotation(180);//箭头设置为向上
isExpand = true;
}
}
};
holder.tvContent.post(new Runnable()
{
@Override
public void run()
{
/**
* 在子线程中获取textview的行数,等页面加载完成之后才能取到行数
*/
int lineCount = holder.tvContent.getLineCount();
if (lineCount > 2)//如果行数大于2,就让textview闭合
{
holder.tvContent.setMaxLines(2);
holder.viewContainer.setOnClickListener(listener);//可以相应点击事件
holder.ivArrow.setVisibility(View.VISIBLE);
} else
{
holder.viewContainer.setOnClickListener(null);//行数没有超过两行,保持原状,无需改变
holder.ivArrow.setVisibility(View.GONE);//让箭头消失
}
}
});
}
@Override
public int getItemCount()
{
return datas.size();
}
class ViewHolder extends RecyclerView.ViewHolder
{
View viewContainer;
TextView tvContent;
ImageView ivArrow;
ViewHolder(View itemView)
{
super(itemView);
viewContainer = itemView.findViewById(R.id.view_item_container);
tvContent = (TextView) itemView.findViewById(R.id.tv_item_content);
ivArrow = (ImageView) itemView.findViewById(R.id.iv_item_arrow);
}
}
}
个人感觉主要用到的知识点就是获取TextView行数,因为lineCount属性是在UI绘制加载完成之后才会有值的,所以不能在主线程中getLineCount();那样取到的值永远都是0.
整个实现思路大致就是这样,当然可以自己根据需求扩展和改进它的功能。
源码