Android分组悬浮列表实现

       在App的开发过程碰到对列表进行分组显示,并且列表在滑动的时候中希望分组悬浮固定在列表的顶部。具体效果图如下

这里写图片描述

       分组悬浮列表的实现是在http://blog.csdn.net/u010335298/article/details/51150346基础上做了相应改进。

一, 分组悬浮列表目标

  • 重写ListView(SectionPinListView)实现分组悬浮列表,不破会ListView原有的所有功能。
  • 重写BaseAdapter(SectionPinAdapter)尽量重写BaseAdapter的负担。
  • 对ListView上拉刷新,下拉加载更多的时候分组悬浮还有效果。
  • SectionPinListView既可以设置重写的SectionPinAdapter,也可以不设置,如果设置的不是重写的SectionPinAdapter是没有分组悬浮的效果。

二, 分组悬浮列表代码

       要实现分组悬浮列表,那得在ListView滚动的时候不管滚动到哪个位置,都得知道当前哪个分组要悬浮在顶部,在得到这个View之后重写ListView的dispatchDraw()方法把这个分组View画在ListView的顶部整个功能就实现了。总得来说就两件事:一件滚动的时候拿到要悬浮的分组View、第二件把这个View画到顶部。

  • ListView滚动的过程中得到要悬浮的View:
    既然是在滚动过程中得到要悬浮的View,那得去监听onScroller事件,在onScroll()里面去处理,这里悬浮的View说白了也是ListView里面的一个子View,Adapter里面有一个获取View的方法,那知道adapter中的position就搞定了,下面直接贴实现的代码。
    /**
     * @param absListView      ListView
     * @param firstVisibleItem 当前能看见的第一个列表项ID(从0开始)
     * @param visibleItemCount 当前能看见的列表项个数(小半个也算,并且header views 和 footer views 也算在里面了)
     * @param totalItemCount   列表项总是 (header count + adapter count + footer count)
     */
    @Override
    public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        if (mScrollListener != null) {
            mScrollListener.onScroll(absListView, firstVisibleItem, visibleItemCount, totalItemCount);
        }
        if (getAdapter() != null && !(getAdapter() instanceof SectionPinAdapter)) {
            return;
        }
        int headerViewCount = getHeaderViewsCount();
        if (getAdapter() == null || !mSectionPinEnable || firstVisibleItem < headerViewCount) {
            /**
             * 第一个section都还没出来
             */
            mViewSectionPin = null;
            mSectionPinOffset = 0f;
            mSectionPinAdapterPosition = -1;
            for (int i = 0; i < visibleItemCount; i++) {
                View view = getChildAt(i);
                if (view != null) {
                    view.setVisibility(VISIBLE);
                }
            }
            return;
        }
        if (getAdapter().getCount() <= 0) {
            return;
        }
        int adapterFirstVisibleItem = firstVisibleItem - headerViewCount;
        int pinViewAdapterPosition = getPinViewAdapterPosition(adapterFirstVisibleItem);
        if (pinViewAdapterPosition != -1 && mSectionPinAdapterPosition != pinViewAdapterPosition) {
            /**
             * pin view 被换掉了
             */
            mViewSectionPin = getSectionPinView(pinViewAdapterPosition);
            ensurePinViewLayout(mViewSectionPin);
        }
        if (mViewSectionPin == null) {
            return;
        }

        mSectionPinOffset = 0f;
        /**
         * 遍历所有可见的View
         */
        for (int index = 0; index < visibleItemCount; index++) {
            int adapterPosition = index + adapterFirstVisibleItem;
            /**
             * 判断是不是section
             */
            SectionPinAdapter adapter = (SectionPinAdapter) getAdapter();
            if (adapter.isSection(adapterPosition)) {
                View sectionView = getChildAt(index);
                int sectionTop = sectionView.getTop();
                int pinViewHeight = mViewSectionPin.getHeight();
                sectionView.setVisibility(VISIBLE);
                if (sectionTop < pinViewHeight && sectionTop > 0) {
                    mSectionPinOffset = sectionTop - pinViewHeight;
                } else if (sectionTop <= 0) {
                    sectionView.setVisibility(INVISIBLE);
                }

            }
        }
        invalidate();
    }
  • 分组悬浮View画在ListView的顶部:
    在拿到了要悬浮的View之后要在ListView中draw出来了。
    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);

        if (getAdapter() == null || !(getAdapter() instanceof SectionPinAdapter) || mViewSectionPin == null || !mSectionPinEnable) {
            return;
        }
        int saveCount = canvas.save();
        /**
         * canvas垂直平移
         */
        canvas.translate(0, mSectionPinOffset);
        canvas.clipRect(0, 0, getWidth(), mViewSectionPin.getMeasuredHeight()); // needed
        mViewSectionPin.draw(canvas);
        canvas.restoreToCount(saveCount);
    }

最后直接贴代码出来,代码中看起来可能更加的连贯,更加的详细
https://github.com/tuacy/SectionPin

RecyclerView 实现同样的功能请参考链接 RecyclerView分组悬浮列表

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值