Simple list view

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;
    }

}

2 Comments

#
Alex - December 11, 2009 at 2:41 a.m.

not so simple now is it?

#
Steve Madden - January 1, 2010 at 7:16 p.m.

doesn't look simple at all :)

Add a Comment