Android RecyclerView 2レベルリスト実装

17035 ワード

  • Android RecyclerView 2レベルリスト実装
  • 概要
  • 実装基盤
  • 実現構想
  • 実装プロセス
  • 二次リストデータフォーマット
  • RecyclerView Itemステータス
  • ViewHolder
  • その他の属性と方法
  • getItemStatusByPositionメソッド実装
  • getItemCountメソッド実装
  • その他の方法実装
  • まとめ

  • Android RecyclerView 2レベルリスト実装
    2017.5.16 demoを追加
    Demo
    簡単に述べる
    Androidアプリを開発する際には、どうしても2級リストを実現する必要がありますが、自分のプロジェクトで使用しているリストはandroid.support.v7.widgetパッケージの中のRecyclerViewで、場合によっては異なるスタイルのリストを実現でき、拡張性が高いというメリットがあります.悪いところは何でも自分で実現しなければならない.だからRecyclerViewで実現しようとした二級リストには、ListViewのようなExpandableListViewがなく、自分で実現するしかないことに気づいた.
    実装ベースRecyclerViewを使用する場合は、ListViewと同様に、Adapterを作成してRecyclerViewがどのように動作するかを示す必要があります.RecyclerViewを作成する場合は、Adapterを再ロードする必要があります.onCreateViewHolder()タイプViewHolder取得onBindViewHolder()合計ロードitemを返します.
    Created with Raphaël 2.1.0 Start getItemCount() getItemViewType() onCreateViewHolder() onBindViewHolder() End
    また、カスタムgetItemViewType()を探すための各コントロールも作成する必要があります.
    実現構想.
    以上より,二次リストを実現するにあたって,onCreateViewHolderおよびitemにおいて,一次プロジェクト(GroupItem)がロードされるか,二次サブプロジェクト(SubItem)がロードされるかを判断する.
    インプリメンテーションプロセス
    二次リストデータフォーマット
    一般に、1つのGroupItemの下に1つ、または複数のSubItemがあり、1対多である.ここで、このデータフォーマットは、以下のコードでカプセル化されるgetItemCount()でカプセル化される.
    public class DataTree<K, V> {
    
        private K groupItem;
        private List subItems;
    
        public DataTree(K groupItem, List subItems) {
            this.groupItem = groupItem;
            this.subItems = subItems;
        }
    
        public K getGroupItem() {
            return groupItem;
        }
    
        public List getSubItems() {
            return subItems;
        }
    }

    RecyclerView Itemステータスitemカプセル化リストの各項目の状態は、RecyclerViewitemのタイプ、group itemまたはsubitemViewHolder一級インデックス位置itemitemが二級サブプロジェクトである場合、サブプロジェクトインデックスを保存する
        private static class ItemStatus {
    
            public static final int VIEW_TYPE_GROUPITEM = 0;
            public static final int VIEW_TYPE_SUBITEM = 1;
    
            private int viewType;
            private int groupItemIndex = 0;
            private int subItemIndex = -1;
    
            public ItemStatus() {
            }
    
            public int getViewType() {
                return viewType;
            }
    
            public void setViewType(int viewType) {
                this.viewType = viewType;
            }
    
            public int getGroupItemIndex() {
                return groupItemIndex;
            }
    
            public void setGroupItemIndex(int groupItemIndex) {
                this.groupItemIndex = groupItemIndex;
            }
    
            public int getSubItemIndex() {
                return subItemIndex;
            }
    
            public void setSubItemIndex(int subItemIndex) {
                this.subItemIndex = subItemIndex;
            }
        }

    ViewHolder
    ここのonCreateViewHolder()onBindViewHolder()はそれぞれ異なるレイアウトファイルを使っているので、私はDataTreeを別々に書いて、以下のようにします.
        public static class GroupItemViewHolder extends RecyclerView.ViewHolder {
            ...
            public GroupItemViewHolder(View itemView) {
                super(itemView);
                ...
            }
        }
    
        public static class SubItemViewHolder extends RecyclerView.ViewHolder {
            ...
            public SubItemViewHolder(View itemView) {
                super(itemView);
                ...
            }
        }

    その他のプロパティとメソッドItemStatusviewType表示用データgroupItemIndex保存subItemIndexステータス
        //             
        public void setDataTrees(List> dt) {
            this.dataTrees = dt;
            initGroupItemStatus(groupItemStatus);
            notifyDataSetChanged();
        }
    
        //     ,   groupItem        
        private void initGroupItemStatus(List l) {
            for (int i = 0; i < dataTrees.size(); i++) {
                l.add(false);
            }
        }

    getItemStatusByPosition()メソッド実装
    名前の通り、groupItemに基づいてそのsubItemを判断する状態を計算し、1つのViewHolderを返すために使用される.
    コードは次のとおりです.
    private ItemStatus getItemStatusByPosition(int position) {
    
            ItemStatus itemStatus = new ItemStatus();
    
            int count = 0;    //  groupItemIndex = i  ,position   
            int i = 0;
    
            //   groupItem      
            for (i = 0; i < groupItemStatus.size(); i++ ) {
    
                //pos       ,item groupItem
                if (count == position) {
                    itemStatus.setViewType(ItemStatus.VIEW_TYPE_GROUPITEM);
                    itemStatus.setGroupItemIndex(i);
                    break;
    
                //pos     ,item groupItem(i - 1)    subItem
                } else if (count > position) {
    
                    itemStatus.setViewType(ItemStatus.VIEW_TYPE_SUBITEM);
                    itemStatus.setGroupItemIndex(i - 1);
                    itemStatus.setSubItemIndex(position - ( count - dataTrees.get(i - 1).getSubItems().size() ) );
                    break;
    
                }
    
                //  groupItem       ,         ,  count++
                count++;
    
                //     groupItem    “ ”  ,count     groupItem        
                if (groupItemStatus.get(i)) {
    
                    count += dataTrees.get(i).getSubItems().size();
    
                }
    
    
            }
    
            //             groupItem   
            if (i >= groupItemStatus.size()) {
                itemStatus.setGroupItemIndex(i - 1);
                itemStatus.setViewType(ItemStatus.VIEW_TYPE_SUBITEM);
                itemStatus.setSubItemIndex(position - ( count - dataTrees.get(i - 1).getSubItems().size() ) );
            }
    
            return itemStatus;
        }

    getItemCount()メソッド実装
    このメソッドはリストを表示するときに複数回実行され、返された項目のカウントが正しくないとプログラムがエラーで潰れ、コードは以下の通りです.
        @Override
        public int getItemCount() {
    
            Logger.i("1");
    
            int itemCount = 0;
    
            if (groupItemStatus.size() == 0) {
                return 0;
            }
    
            for (int i = 0; i < dataTrees.size(); i++) {
    
                if (groupItemStatus.get(i)) {
                    itemCount += dataTrees.get(i).getSubItems().size() + 1;
                } else {
                    itemCount++;
                }
    
            }
    
            return itemCount;
        }

    その他の方法の実装
  • getItemViewType()

  • このメソッドは、contextの前に実行され、list dataTreesが返されます.コードは次のとおりです.
        @Override
        public int getItemViewType(int position) {
            return getItemStatusByPosition(position).getViewType();
        }
  • onCreateViewHolder()は、list groupItemStatusで返されるgroupItemによって異なるプロジェクトレイアウトを選択します.コードは次のとおりです.
  •     @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View v;
            RecyclerView.ViewHolder viewHolder = null;
    
            if (viewType == ItemStatus.VIEW_TYPE_GROUPITEM) {
    
                v = LayoutInflater.from(parent.getContext()).inflate(R.layout
                        .item_artist_detail_album, parent, false);
                viewHolder = new GroupItemViewHolder(v);
    
            } else if (viewType == ItemStatus.VIEW_TYPE_SUBITEM) {
    
                v = LayoutInflater.from(parent.getContext()).inflate(R.layout
                        .item_artist_detail_track, parent, false);
                viewHolder = new SubItemViewHolder(v);
            }
    
            return viewHolder;
        }
  • onBindViewHolder()は、異なるpositionに基づいて異なるitemをバインドし、コードは以下の通りである:
  •    @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    
            final ItemStatus itemStatus = getItemStatusByPosition(position);
    
            final DataTree dt = dataTrees.get(itemStatus.getGroupItemIndex());
    
            if ( itemStatus.getViewType() == ItemStatus.VIEW_TYPE_GROUPITEM ) {
    
                final GroupItemViewHolder groupItemVh = (GroupItemViewHolder) holder;
    
                . . .    //  groupItem,  groupItem  
    
                groupItemVh.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
    
                        int groupItemIndex = itemStatus.getGroupItemIndex();
    
                        if ( !groupItemStatus.get(groupItemIndex) ) {
    
                            . . .  //groupItem “  ”   “  ”  
    
                            groupItemStatus.set(groupItemIndex, true);
                            notifyItemRangeInserted(groupItemVh.getAdapterPosition() + 1, dt.getSubItems().size());
    
                        } else {
    
                         . . .    //groupItem “  ”   “  ”  
    
                        groupItemStatus.set(groupItemIndex, false);
                            notifyItemRangeRemoved(groupItemVh.getAdapterPosition() + 1, dt.getSubItems().size());
    
                        }
    
                    }
                });
    
            } else if (itemStatus.getViewType() == ItemStatus.VIEW_TYPE_SUBITEM) {
    
                SubItemViewHolder subItemVh = (SubItemViewHolder) holder;
    
                 . . .    //  subItem,  subItem  
    
                subItemVh.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
    
                     . . .    //  subItem  
    
                    }
                });
            }
        }

    まとめ
    二級リストはItemStatusを小さく拡張し、実現の過程で、少し面倒な点は特定のonCreateViewHolder()を識別することであり、すなわちint viewTypeの実現であり、ここでは簡単にポーリングを巡る方法で判断すると、より簡単でリソースを節約する方法があるはずだ.2次リストを実装した後,理論的にはマルチレベルリストを実装することができ,試してみることができる.
    に付随
    この方法で実現する前に、getItemViewType()が提供する方法であるviewTypeを試みたことがあるが、viewTypeのロードメカニズムにより、リストがインタフェースから切り出されると破棄され、再び表示されると、ViewHolderは以前のものではなく新しいRecyclerViewを再作成するので、以前のitemは見えなくなり、最後に実現できなかったので、興味のある方は試してみてください.
    [Android RecyclerViewは完全解析体験芸術的なコントロール-hongyang-CSDNブログを使用]http://blog.csdn.net/lmj623565791/article/details/45059587 ↩