Android多級樹形結構列表(理論上可以無限級)

轉載請註明出處 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>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章