setSelector 自定义ListView

setSelector custom ListView

我正在使用名为 headerListView 的自定义列表视图,我正在尝试设置选择器/点击颜色。现在,在常规列表视图中,我是这样做的。

StateListDrawable selector = new StateListDrawable();
    ColorDrawable clickedColor = new ColorDrawable(colorBar);
    ColorDrawable transparent = new ColorDrawable(Color.TRANSPARENT);

    selector.addState(new int[]{android.R.attr.state_pressed}, clickedColor);
    selector.addState(new int[]{}, transparent);
    list.setSelector(selector);

但是 HeaderListView 没有 setSelector 方法,所以我想做一个,但我不确定它的作用/它是如何工作的,这里是自定义列表视图。

public class HeaderListView extends RelativeLayout {

// TODO: Handle listViews with fast scroll
// TODO: See if there are methods to dispatch to mListView

private static final int FADE_DELAY    = 1000;
private static final int FADE_DURATION = 2000;

private InternalListView mListView;
private SectionAdapter   mAdapter;
private RelativeLayout   mHeader;
private FrameLayout      mScrollView;
private AbsListView.OnScrollListener mExternalOnScrollListener;

public HeaderListView(Context context) {
    super(context);
    init(context, null);
}

public HeaderListView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context, attrs);
}

private void init(Context context, AttributeSet attrs) {
    mListView = new InternalListView(getContext(), attrs);
    LayoutParams listParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    listParams.addRule(ALIGN_PARENT_TOP);
    mListView.setLayoutParams(listParams);
    mListView.setOnScrollListener(new HeaderListViewOnScrollListener());
    mListView.setVerticalScrollBarEnabled(false);
    mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            if (mAdapter != null) {
                mAdapter.onItemClick(parent, view, position, id);
            }
        }
    });
    addView(mListView);

    mHeader = new RelativeLayout(getContext());
    LayoutParams headerParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
    headerParams.addRule(ALIGN_PARENT_TOP);
    mHeader.setLayoutParams(headerParams);
    mHeader.setGravity(Gravity.BOTTOM);
    addView(mHeader);

    // The list view's scroll bar can be hidden by the header, so we display our own scroll bar instead
    Drawable scrollBarDrawable = getResources().getDrawable(R.drawable.scrollbar_handle_holo_light);
    mScrollView = new FrameLayout(getContext());
    LayoutParams scrollParams = new LayoutParams(scrollBarDrawable.getIntrinsicWidth(), LayoutParams.MATCH_PARENT);
    scrollParams.addRule(ALIGN_PARENT_RIGHT);
    scrollParams.rightMargin = (int) dpToPx(2);
    mScrollView.setLayoutParams(scrollParams);

    ImageView scrollIndicator = new ImageView(context);
    scrollIndicator.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
    scrollIndicator.setImageDrawable(scrollBarDrawable);
    scrollIndicator.setScaleType(ScaleType.FIT_XY);
    mScrollView.addView(scrollIndicator);
    mScrollView.setVisibility(INVISIBLE);

    addView(mScrollView);
}

public void setAdapter(SectionAdapter adapter) {
    mAdapter = adapter;
    mListView.setAdapter(adapter);
}

public void setOnScrollListener(AbsListView.OnScrollListener l) {
    mExternalOnScrollListener = l;
}

private class HeaderListViewOnScrollListener implements AbsListView.OnScrollListener {

    private int            previousFirstVisibleItem = -1;
    private int            direction                = 0;
    private int            actualSection            = 0;
    private boolean        scrollingStart           = false;
    private boolean        doneMeasuring            = false;
    private int            lastResetSection         = -1;
    private int            nextH;
    private int            prevH;
    private View           previous;
    private View           next;
    private AlphaAnimation fadeOut                  = new AlphaAnimation(1f, 0f);
    private boolean        noHeaderUpToHeader       = false;
    private boolean        didScroll = false;

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        if (mExternalOnScrollListener != null) {
            mExternalOnScrollListener.onScrollStateChanged(view, scrollState);
        }
        didScroll = true;
    }


    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        if (mExternalOnScrollListener != null) {
            mExternalOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
        }

        if (!didScroll) {
            return;
        }

        firstVisibleItem -= mListView.getHeaderViewsCount();
        if (firstVisibleItem < 0) {
            mHeader.removeAllViews();
            return;
        }

        updateScrollBar();
        if (visibleItemCount > 0 && firstVisibleItem == 0 && mHeader.getChildAt(0) == null) {
            addSectionHeader(0);
            lastResetSection = 0;
        }

        int realFirstVisibleItem = getRealFirstVisibleItem(firstVisibleItem, visibleItemCount);
        if (totalItemCount > 0 && previousFirstVisibleItem != realFirstVisibleItem) {
            direction = realFirstVisibleItem - previousFirstVisibleItem;

            actualSection = mAdapter.getSection(realFirstVisibleItem);

            boolean currIsHeader = mAdapter.isSectionHeader(realFirstVisibleItem);
            boolean prevHasHeader = mAdapter.hasSectionHeaderView(actualSection - 1);
            boolean nextHasHeader = mAdapter.hasSectionHeaderView(actualSection + 1);
            boolean currHasHeader = mAdapter.hasSectionHeaderView(actualSection);
            boolean currIsLast = mAdapter.getRowInSection(realFirstVisibleItem) == mAdapter.numberOfRows(actualSection) - 1;
            boolean prevHasRows = mAdapter.numberOfRows(actualSection - 1) > 0;
            boolean currIsFirst = mAdapter.getRowInSection(realFirstVisibleItem) == 0;

            boolean needScrolling = currIsFirst && !currHasHeader && prevHasHeader && realFirstVisibleItem != firstVisibleItem;
            boolean needNoHeaderUpToHeader = currIsLast && currHasHeader && !nextHasHeader && realFirstVisibleItem == firstVisibleItem && Math.abs(mListView.getChildAt(0).getTop()) >= mListView.getChildAt(0).getHeight() / 2;

            noHeaderUpToHeader = false;
            if (currIsHeader && !prevHasHeader && firstVisibleItem >= 0) {
                resetHeader(direction < 0 ? actualSection - 1 : actualSection);
            } else if ((currIsHeader && firstVisibleItem > 0) || needScrolling) {
                if (!prevHasRows) {
                    resetHeader(actualSection-1);
                }
                startScrolling();
            } else if (needNoHeaderUpToHeader) {
                noHeaderUpToHeader = true;
            } else if (lastResetSection != actualSection) {
                resetHeader(actualSection);
            }

            previousFirstVisibleItem = realFirstVisibleItem;
        }

        if (scrollingStart) {
            int scrolled = realFirstVisibleItem >= firstVisibleItem ? mListView.getChildAt(realFirstVisibleItem - firstVisibleItem).getTop() : 0;

            if (!doneMeasuring) {
                setMeasurements(realFirstVisibleItem, firstVisibleItem);
            }

            int headerH = doneMeasuring ? (prevH - nextH) * direction * Math.abs(scrolled) / (direction < 0 ? nextH : prevH) + (direction > 0 ? nextH : prevH) : 0;

            mHeader.scrollTo(0, -Math.min(0, scrolled - headerH));
            if (doneMeasuring && headerH != mHeader.getLayoutParams().height) {
                LayoutParams p = (LayoutParams) (direction < 0 ? next.getLayoutParams() : previous.getLayoutParams());
                p.topMargin = headerH - p.height;
                mHeader.getLayoutParams().height = headerH;
                mHeader.requestLayout();
            }
        }

        if (noHeaderUpToHeader) {
            if (lastResetSection != actualSection) {
                addSectionHeader(actualSection);
                lastResetSection = actualSection + 1;
            }
            mHeader.scrollTo(0, mHeader.getLayoutParams().height - (mListView.getChildAt(0).getHeight() + mListView.getChildAt(0).getTop()));
        }
    }

    private void startScrolling() {
        scrollingStart = true;
        doneMeasuring = false;
        lastResetSection = -1;
    }

    private void resetHeader(int section) {
        scrollingStart = false;
        addSectionHeader(section);
        mHeader.requestLayout();
        lastResetSection = section;
    }

    private void setMeasurements(int realFirstVisibleItem, int firstVisibleItem) {

        if (direction > 0) {
            nextH = realFirstVisibleItem >= firstVisibleItem ? mListView.getChildAt(realFirstVisibleItem - firstVisibleItem).getMeasuredHeight() : 0;
        }

        previous = mHeader.getChildAt(0);
        prevH = previous != null ? previous.getMeasuredHeight() : mHeader.getHeight();

        if (direction < 0) {
            if (lastResetSection != actualSection - 1) {
                addSectionHeader(Math.max(0, actualSection - 1));
                next = mHeader.getChildAt(0);
            }
            nextH = mHeader.getChildCount() > 0 ? mHeader.getChildAt(0).getMeasuredHeight() : 0;
            mHeader.scrollTo(0, prevH);
        }
        doneMeasuring = previous != null && prevH > 0 && nextH > 0;
    }

    private void updateScrollBar() {
        if (mHeader != null && mListView != null && mScrollView != null) {
            int offset = mListView.computeVerticalScrollOffset();
            int range = mListView.computeVerticalScrollRange();
            int extent = mListView.computeVerticalScrollExtent();
            mScrollView.setVisibility(extent >= range ? View.INVISIBLE : View.VISIBLE);
            if (extent >= range) {
                return;
            }
            int top = range == 0 ? mListView.getHeight() : mListView.getHeight() * offset / range;
            int bottom = range == 0 ? 0 : mListView.getHeight() - mListView.getHeight() * (offset + extent) / range;
            mScrollView.setPadding(0, top, 0, bottom);
            fadeOut.reset();
            fadeOut.setFillBefore(true);
            fadeOut.setFillAfter(true);
            fadeOut.setStartOffset(FADE_DELAY);
            fadeOut.setDuration(FADE_DURATION);
            mScrollView.clearAnimation();
            mScrollView.startAnimation(fadeOut);
        }
    }

    private void addSectionHeader(int actualSection) {
        View previousHeader = mHeader.getChildAt(0);
        if (previousHeader != null) {
            mHeader.removeViewAt(0);
        }

        if (mAdapter.hasSectionHeaderView(actualSection)) {
            View header = mAdapter.getSectionHeaderView(actualSection, null, null);
            header.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));

            header.measure(MeasureSpec.makeMeasureSpec(mHeader.getWidth(), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));

            mHeader.getLayoutParams().height = header.getMeasuredHeight();
            header.scrollTo(0, 0);
            mHeader.scrollTo(0, 0);
            mHeader.addView(header, 0);
        } else {
            mHeader.getLayoutParams().height = 0;
            mHeader.scrollTo(0, 0);
        }

        mScrollView.bringToFront();
    }

    private int getRealFirstVisibleItem(int firstVisibleItem, int visibleItemCount) {
        if (visibleItemCount == 0) {
            return -1;
        }
        int relativeIndex = 0, totalHeight = mListView.getChildAt(0).getTop();
        for (relativeIndex = 0; relativeIndex < visibleItemCount && totalHeight < mHeader.getHeight(); relativeIndex++) {
            totalHeight += mListView.getChildAt(relativeIndex).getHeight();
        }
        int realFVI = Math.max(firstVisibleItem, firstVisibleItem + relativeIndex - 1);
        return realFVI;
    }
}

public ListView getListView() {
    return mListView;
}

public void addHeaderView(View v) {
    mListView.addHeaderView(v);
}

private float dpToPx(float dp) {
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getContext().getResources().getDisplayMetrics());
}

protected class InternalListView extends ListView {

    public InternalListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected int computeVerticalScrollExtent() {
        return super.computeVerticalScrollExtent();
    }

    @Override
    protected int computeVerticalScrollOffset() {
        return super.computeVerticalScrollOffset();
    }

    @Override
    protected int computeVerticalScrollRange() {
        return super.computeVerticalScrollRange();
    }
}
}

任何帮助将不胜感激:)

可以设置listView.setSelector(选择器); HeaderListView class.

中的 init() 方法内部