A view with the similar visual effect as ListView, but doesn't require an adapter. It is useful
to display a small number of items as a list. It can better handle the scroll bar than ListView
when the items have different heights.
Extending LinearLayout seems more elegant, but requires more code.
package ...;
import ...;
/**
* A view with the similar visual effect as ListView, but doesn't require an adapter. It is useful
* to display a small number of items as a list. It can better handle the scroll bar than ListView
* when the items have different heights.
*/
public class SimpleListView extends ListView {
final ArrayList<View> mViews = new ArrayList<View>();
final ArrayList<Object> mData = new ArrayList<Object>();
final BitSet mEnabled = new BitSet();
private final SimpleAdapter mAdapter = new SimpleAdapter();
private int mScrollRange;
private boolean mScrollToTopPending;
class SimpleAdapter extends BaseAdapter {
public int getCount() {
return mViews.size();
}
public Object getItem(int position) {
return mData.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
return mViews.get(position);
}
@Override
public boolean areAllItemsEnabled() {
return false;
}
@Override
public boolean isEnabled(int position) {
return mEnabled.get(position);
}
@Override
public int getItemViewType(int position) {
// Don't let ListView try to reuse the views.
return AdapterView.ITEM_VIEW_TYPE_IGNORE;
}
}
public SimpleListView(Context context) {
super(context);
setAdapter(mAdapter);
}
public SimpleListView(Context context, AttributeSet attrs) {
super(context, attrs);
setAdapter(mAdapter);
}
public SimpleListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setAdapter(mAdapter);
}
public void addView(View view, Object data, boolean enabled) {
mViews.add(view);
mData.add(data);
if (enabled) mEnabled.set(mViews.size() - 1);
mAdapter.notifyDataSetChanged();
}
public void clear() {
mViews.clear();
mData.clear();
mEnabled.clear();
mAdapter.notifyDataSetChanged();
scrollToTop();
}
private static final Rect RECT = new Rect(0, 0, 1, 1);
@Override
protected void layoutChildren() {
super.layoutChildren();
int scrollRange = 0;
for (int i = 0, n = mViews.size(); i < n; i++) {
int height = mViews.get(i).getHeight();
// Height == 0 means that the view has not been layout-ed.
if (height == 0) height = 64;
scrollRange += height;
}
mScrollRange = scrollRange;
if (mScrollToTopPending && !mViews.isEmpty()) {
requestChildRectangleOnScreen(mViews.get(0), RECT, true);
mScrollToTopPending = false;
}
}
@Override
protected int computeVerticalScrollExtent() {
return getHeight();
}
@Override
protected int computeVerticalScrollOffset() {
int result = 0;
if (mViews.size() > 0) {
int firstVisible = getFirstVisiblePosition();
for (int i = 0; i < firstVisible; i++) {
result += mViews.get(i).getHeight();
}
result -= mViews.get(firstVisible).getTop();
}
return result;
}
@Override
protected int computeVerticalScrollRange() {
return mScrollRange;
}
public void scrollToTop() {
setSelection(0);
mScrollToTopPending = true;
}
}
Be the first to comment