1 package com.xtremelabs.robolectric.shadows; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import android.util.SparseBooleanArray; 7 import android.view.View; 8 import android.widget.ListAdapter; 9 import android.widget.ListView; 10 11 import com.xtremelabs.robolectric.internal.Implementation; 12 import com.xtremelabs.robolectric.internal.Implements; 13 import com.xtremelabs.robolectric.internal.RealObject; 14 15 @SuppressWarnings({"UnusedDeclaration"}) 16 @Implements(ListView.class) 17 public class ShadowListView extends ShadowAbsListView { 18 @RealObject private ListView realListView; 19 20 private boolean itemsCanFocus; 21 private List<View> headerViews = new ArrayList<View>(); 22 private List<View> footerViews = new ArrayList<View>(); 23 24 private int choiceMode; 25 private SparseBooleanArray checkedItemPositions = new SparseBooleanArray(); 26 27 @Implementation 28 @Override findViewById(int id)29 public View findViewById(int id) { 30 View child = super.findViewById(id); 31 if (child == null) { 32 child = findView(headerViews, id); 33 34 if (child == null) { 35 child = findView(footerViews, id); 36 } 37 } 38 return child; 39 } 40 findView(List<View> views, int viewId)41 private View findView(List<View> views, int viewId) { 42 View child = null; 43 for (View v : views) { 44 child = v.findViewById(viewId); 45 if (child != null) { 46 break; 47 } 48 } 49 return child; 50 } 51 52 53 @Implementation setItemsCanFocus(boolean itemsCanFocus)54 public void setItemsCanFocus(boolean itemsCanFocus) { 55 this.itemsCanFocus = itemsCanFocus; 56 } 57 58 @Implementation 59 @Override performItemClick(View view, int position, long id)60 public boolean performItemClick(View view, int position, long id) { 61 boolean handled = false; 62 if (choiceMode != ListView.CHOICE_MODE_NONE) { 63 handled = true; 64 65 if (choiceMode == ListView.CHOICE_MODE_MULTIPLE) { 66 boolean newValue = !checkedItemPositions.get(position, false); 67 checkedItemPositions.put(position, newValue); 68 } else { 69 boolean newValue = !checkedItemPositions.get(position, false); 70 if (newValue) { 71 checkedItemPositions.clear(); 72 checkedItemPositions.put(position, true); 73 } 74 } 75 } 76 77 handled |= super.performItemClick(view, position, id); 78 return handled; 79 } 80 81 @Implementation setAdapter(ListAdapter adapter)82 public void setAdapter(ListAdapter adapter) { 83 super.setAdapter(adapter); 84 } 85 86 @Implementation addHeaderView(View headerView)87 public void addHeaderView(View headerView) { 88 addHeaderView(headerView, null, true); 89 } 90 91 @Implementation addHeaderView(View headerView, Object data, boolean isSelectable)92 public void addHeaderView(View headerView, Object data, boolean isSelectable) { 93 ensureAdapterNotSet("header"); 94 headerViews.add(headerView); 95 realListView.addView(headerView); 96 } 97 98 @Implementation getHeaderViewsCount()99 public int getHeaderViewsCount() { 100 return headerViews.size(); 101 } 102 103 @Implementation getFooterViewsCount()104 public int getFooterViewsCount() { 105 return footerViews.size(); 106 } 107 108 @Implementation addFooterView(View footerView, Object data, boolean isSelectable)109 public void addFooterView(View footerView, Object data, boolean isSelectable) { 110 ensureAdapterNotSet("footer"); 111 footerViews.add(footerView); 112 realListView.addView(footerView); 113 } 114 115 @Implementation addFooterView(View footerView)116 public void addFooterView(View footerView) { 117 addFooterView(footerView, null, false); 118 } 119 120 @Implementation removeAllViews()121 public void removeAllViews() { 122 throw new UnsupportedOperationException(); 123 } 124 125 @Implementation removeView(View view)126 public void removeView(View view) { 127 throw new UnsupportedOperationException(); 128 } 129 130 @Implementation removeViewAt(int index)131 public void removeViewAt(int index) { 132 throw new UnsupportedOperationException(); 133 } 134 ensureAdapterNotSet(String view)135 private void ensureAdapterNotSet(String view) { 136 if (getAdapter() != null) { 137 throw new IllegalStateException("Cannot add " + view + " view to list -- setAdapter has already been called"); 138 } 139 } 140 isItemsCanFocus()141 public boolean isItemsCanFocus() { 142 return itemsCanFocus; 143 } 144 getHeaderViews()145 public List<View> getHeaderViews() { 146 return headerViews; 147 } 148 setHeaderViews(List<View> headerViews)149 public void setHeaderViews(List<View> headerViews) { 150 this.headerViews = headerViews; 151 } 152 getFooterViews()153 public List<View> getFooterViews() { 154 return footerViews; 155 } 156 setFooterViews(List<View> footerViews)157 public void setFooterViews(List<View> footerViews) { 158 this.footerViews = footerViews; 159 } 160 161 @Override addViews()162 protected void addViews() { 163 for (View headerView : headerViews) { 164 addView(headerView); 165 } 166 167 super.addViews(); 168 169 for (View footerView : footerViews) { 170 addView(footerView); 171 } 172 } 173 174 @Implementation getChoiceMode()175 public int getChoiceMode() { 176 return choiceMode; 177 } 178 179 @Implementation setChoiceMode(int choiceMode)180 public void setChoiceMode(int choiceMode) { 181 this.choiceMode = choiceMode; 182 } 183 184 @Implementation setItemChecked(int position, boolean value)185 public void setItemChecked(int position, boolean value) { 186 if (choiceMode == ListView.CHOICE_MODE_SINGLE) { 187 checkedItemPositions.clear(); 188 checkedItemPositions.put(position, value); 189 } else if (choiceMode == ListView.CHOICE_MODE_MULTIPLE) { 190 checkedItemPositions.put(position, value); 191 } 192 } 193 194 @Implementation getCheckedItemPosition()195 public int getCheckedItemPosition() { 196 if (choiceMode != ListView.CHOICE_MODE_SINGLE || checkedItemPositions.size() != 1) 197 return ListView.INVALID_POSITION; 198 199 return checkedItemPositions.keyAt(0); 200 } 201 202 @Implementation getCheckedItemPositions()203 public SparseBooleanArray getCheckedItemPositions() { 204 if (choiceMode == ListView.CHOICE_MODE_NONE) 205 return null; 206 207 return checkedItemPositions; 208 } 209 } 210