轉載請註明出處 http://blog.csdn.net/stevenduan17
最近有需求做多級樹形結構的列表,使用ExpandableListView不能實現,無奈,只能自己寫了,主要時層級之間使用padding來體現層級關係,先看效果
話不多說,直接上代碼
主界面及列表實現
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getName();
@BindView(R.id.mRecyclerView)
RecyclerView mRecyclerView;
private MyAdapter myAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
getSupportActionBar().setTitle("多級樹列表");
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
myAdapter = new MyAdapter();
mRecyclerView.setAdapter(myAdapter);
//先初始化兩條數據
addData(1, 0);
}
class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private List<Node> list = new ArrayList<>();
public void addItem(int position, Node node) {
list.add(position, node);
notifyItemInserted(position);
Log.d(TAG, "addItem: " + position);
}
public class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.mImageView)
ImageView mImageView;
@BindView(R.id.mTextView)
TextView mTextView;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false);
return new ViewHolder(itemView);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
Node node = list.get(position);
//最後一級時把展開收起三角圖片隱藏
holder.mImageView.setVisibility(node.getLevel() == 4 ? View.GONE : View.VISIBLE);
//展開或收起圖標
holder.mImageView.setImageResource(node.isExpand() ? R.drawable.ic_expand_more : R.drawable.ic_expand_less);
holder.mTextView.setText(node.getName());
//縮進控制 界面層級關係
holder.itemView.setPadding(node.getLevel() * dpToPx(16f), dpToPx(9f), dpToPx(16f), dpToPx(9f));
//點擊條目展開或收起下一級
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//最好不要把node final
int p = holder.getAdapterPosition();
Node n = list.get(p);
//如果時最後一級 點擊無效
if (n.getLevel() == 4) {
return;
}
//收起或展開下一級
if (n.isExpand()) {
//收起
holder.mImageView.setImageResource(R.drawable.ic_expand_less);
//刪除下一級
removeLevelLower(p, n.getLevel());
//更新伸展狀態
setItemExpand(p, false);
} else {
//展開 加載下一級
holder.mImageView.setImageResource(R.drawable.ic_expand_more);
//添加下一級數據 這裏只是假數據
addData(n.getLevel() + 1, p + 1);
setItemExpand(p, true);
}
}
});
}
@Override
public int getItemCount() {
return list == null ? 0 : list.size();
}
/**
* 移除當前節點下所有子節點
*
* @param position
* @param level
*/
private void removeLevelLower(int position, int level) {
int size = list.size();
int i = 0;
List<Node> nodeList = new ArrayList<>();
while (position + (++i) < size && list.get(position + i).getLevel() > level) {
nodeList.add(list.get(position + i));
}
Log.d(TAG, "需要移除下級節點數量:" + nodeList.size());
if (!nodeList.isEmpty()) {
list.removeAll(nodeList);
notifyItemRangeRemoved(position + 1, position + i);
mRecyclerView.scrollToPosition(position);
}
}
/**
* 更新條目伸縮狀態
*
* @param position
* @param expand
*/
public void setItemExpand(int position, boolean expand) {
Node item = list.get(position);
item.setExpand(expand);
list.set(position, item);
}
}
/**
* 添加數據
*
* @param level
*/
private void addData(int level, int position) {
//測試數據 一般是異步請求得到的數據
for (int i = 0; i < 3; i++) {
myAdapter.addItem(position++, new Node(UUID.randomUUID().toString(), level, false));
}
Log.d(TAG, "添加數據");
}
/**
* dp轉px
*
* @param dp
* @return
*/
private int dpToPx(float dp) {
float density = getResources().getDisplayMetrics().density;
return (int) (dp * density + 0.5f);
}
}
activity_main.xml 只是一個RecyclerView
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/mRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>
item_layout.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:background="@drawable/bg_white_with_bottom_border"
android:orientation="horizontal">
<ImageView
android:id="@+id/mImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_expand_less"/>
<TextView
android:id="@+id/mTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_name"/>
</LinearLayout>