1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.documentsui; 18 19 import android.view.View; 20 import android.view.ViewGroup; 21 import android.widget.AdapterView; 22 import android.widget.BaseAdapter; 23 import android.widget.ListAdapter; 24 25 import java.util.ArrayList; 26 27 /** 28 * Adapter that combines multiple adapters as sections, asking each section to 29 * provide a header, and correctly handling item types across child adapters. 30 */ 31 public class SectionedListAdapter extends BaseAdapter { 32 private ArrayList<SectionAdapter> mSections = new ArrayList<>(); 33 34 public interface SectionAdapter extends ListAdapter { 35 public View getHeaderView(View convertView, ViewGroup parent); 36 } 37 38 public void clearSections() { 39 mSections.clear(); 40 notifyDataSetChanged(); 41 } 42 43 /** 44 * After mutating sections, you <em>must</em> 45 * {@link AdapterView#setAdapter(android.widget.Adapter)} to correctly 46 * recount view types. 47 */ 48 public void addSection(SectionAdapter adapter) { 49 mSections.add(adapter); 50 notifyDataSetChanged(); 51 } 52 53 @Override 54 public int getCount() { 55 int count = 0; 56 final int size = mSections.size(); 57 for (int i = 0; i < size; i++) { 58 count += mSections.get(i).getCount() + 1; 59 } 60 return count; 61 } 62 63 @Override 64 public Object getItem(int position) { 65 final int size = mSections.size(); 66 for (int i = 0; i < size; i++) { 67 final SectionAdapter section = mSections.get(i); 68 final int sectionSize = section.getCount() + 1; 69 70 // Check if position inside this section 71 if (position == 0) { 72 return section; 73 } else if (position < sectionSize) { 74 return section.getItem(position - 1); 75 } 76 77 // Otherwise jump into next section 78 position -= sectionSize; 79 } 80 throw new IllegalStateException("Unknown position " + position); 81 } 82 83 @Override 84 public long getItemId(int position) { 85 return position; 86 } 87 88 @Override 89 public View getView(int position, View convertView, ViewGroup parent) { 90 final int size = mSections.size(); 91 for (int i = 0; i < size; i++) { 92 final SectionAdapter section = mSections.get(i); 93 final int sectionSize = section.getCount() + 1; 94 95 // Check if position inside this section 96 if (position == 0) { 97 return section.getHeaderView(convertView, parent); 98 } else if (position < sectionSize) { 99 return section.getView(position - 1, convertView, parent); 100 } 101 102 // Otherwise jump into next section 103 position -= sectionSize; 104 } 105 throw new IllegalStateException("Unknown position " + position); 106 } 107 108 @Override 109 public boolean areAllItemsEnabled() { 110 return false; 111 } 112 113 @Override 114 public boolean isEnabled(int position) { 115 final int size = mSections.size(); 116 for (int i = 0; i < size; i++) { 117 final SectionAdapter section = mSections.get(i); 118 final int sectionSize = section.getCount() + 1; 119 120 // Check if position inside this section 121 if (position == 0) { 122 return false; 123 } else if (position < sectionSize) { 124 return section.isEnabled(position - 1); 125 } 126 127 // Otherwise jump into next section 128 position -= sectionSize; 129 } 130 throw new IllegalStateException("Unknown position " + position); 131 } 132 133 @Override 134 public int getItemViewType(int position) { 135 int type = 1; 136 final int size = mSections.size(); 137 for (int i = 0; i < size; i++) { 138 final SectionAdapter section = mSections.get(i); 139 final int sectionSize = section.getCount() + 1; 140 141 // Check if position inside this section 142 if (position == 0) { 143 return 0; 144 } else if (position < sectionSize) { 145 return type + section.getItemViewType(position - 1); 146 } 147 148 // Otherwise jump into next section 149 position -= sectionSize; 150 type += section.getViewTypeCount(); 151 } 152 throw new IllegalStateException("Unknown position " + position); 153 } 154 155 @Override 156 public int getViewTypeCount() { 157 int count = 1; 158 final int size = mSections.size(); 159 for (int i = 0; i < size; i++) { 160 count += mSections.get(i).getViewTypeCount(); 161 } 162 return count; 163 } 164 } 165