zoukankan      html  css  js  c++  java
  • PinnedHeaderListView实现删除

    项目中用到四个List集合展示一个页面,并且每个页面都会有一个标题栏.找了半天资料决定用PinnedHeaderListView开源项目.最后需求又来了,需要一个删除的功能,又去网上找资料,发现没有实现删除的demo,于是自己把PinnedHeaderListView源码分析了下,其实也就一个类.下面我贴上代码,希望后面的朋友少走弯路.


    PinnedHeaderListView   实现滚动,重绘,添加回调函数

    import android.content.Context;
    import android.graphics.Canvas;
    import android.util.AttributeSet;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.*;
    import android.widget.AbsListView.OnScrollListener;
    
    public class PinnedHeaderListView extends ListView implements OnScrollListener{
    
        private OnScrollListener mOnScrollListener;
    
        public static interface PinnedSectionedHeaderAdapter {
            public boolean isSectionHeader(int position);
    
            public int getSectionForPosition(int position);
    
            public View getSectionHeaderView(int section, View convertView, ViewGroup parent);
    
            public int getSectionHeaderViewType(int section);
    
            public int getCount();
    
        }
    
        private PinnedSectionedHeaderAdapter mAdapter;
        private View mCurrentHeader;
        private int mCurrentHeaderViewType = 0;
        private float mHeaderOffset;
        private boolean mShouldPin = true;
        private int mCurrentSection = 0;
        private int mWidthMode;
        private int mHeightMode;
    
        public PinnedHeaderListView(Context context) {
            super(context);
            super.setOnScrollListener(this);
        }
    
        public PinnedHeaderListView(Context context, AttributeSet attrs) {
            super(context, attrs);
            super.setOnScrollListener(this);
        }
    
        public PinnedHeaderListView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            super.setOnScrollListener(this);
        }
    
        public void setPinHeaders(boolean shouldPin) {
            mShouldPin = shouldPin;
        }
    
        @Override
        public void setAdapter(ListAdapter adapter) {
            mCurrentHeader = null;
            mAdapter = (PinnedSectionedHeaderAdapter) adapter;
            super.setAdapter(adapter);
        }
    
        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            if (mOnScrollListener != null) {
                mOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
            }
    
            if (mAdapter == null || mAdapter.getCount() == 0 || !mShouldPin || (firstVisibleItem < getHeaderViewsCount())) {
                mCurrentHeader = null;
                mHeaderOffset = 0.0f;
                for (int i = firstVisibleItem; i < firstVisibleItem + visibleItemCount; i++) {
                    View header = getChildAt(i);
                    if (header != null) {
                        header.setVisibility(VISIBLE);
                    }
                }
                return;
            }
    
            firstVisibleItem -= getHeaderViewsCount();
    
            int section = mAdapter.getSectionForPosition(firstVisibleItem);
            int viewType = mAdapter.getSectionHeaderViewType(section);
            mCurrentHeader = getSectionHeaderView(section, mCurrentHeaderViewType != viewType ? null : mCurrentHeader);
            ensurePinnedHeaderLayout(mCurrentHeader);
            mCurrentHeaderViewType = viewType;
    
            mHeaderOffset = 0.0f;
    
            for (int i = firstVisibleItem; i < firstVisibleItem + visibleItemCount; i++) {
                if (mAdapter.isSectionHeader(i)) {
                    View header = getChildAt(i - firstVisibleItem);
                    float headerTop = header.getTop();
                    float pinnedHeaderHeight = mCurrentHeader.getMeasuredHeight();
                    header.setVisibility(VISIBLE);
                    if (pinnedHeaderHeight >= headerTop && headerTop > 0) {
                        mHeaderOffset = headerTop - header.getHeight();
                    } else if (headerTop <= 0) {
                        header.setVisibility(INVISIBLE);
                    }
                }
            }
    
            invalidate();
        }
    
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            if (mOnScrollListener != null) {
                mOnScrollListener.onScrollStateChanged(view, scrollState);
            }
        }
    
        private View getSectionHeaderView(int section, View oldView) {
            boolean shouldLayout = section != mCurrentSection || oldView == null;
    
            View view = mAdapter.getSectionHeaderView(section, oldView, this);
            if (shouldLayout) {
                // a new section, thus a new header. We should lay it out again
                ensurePinnedHeaderLayout(view);
                mCurrentSection = section;
            }
            return view;
        }
    
        private void ensurePinnedHeaderLayout(View header) {
            if (header.isLayoutRequested()) {
                int widthSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), mWidthMode);
                
                int heightSpec;
                ViewGroup.LayoutParams layoutParams = header.getLayoutParams();
                if (layoutParams != null && layoutParams.height > 0) {
                    heightSpec = MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY);
                } else {
                    heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
                }
                header.measure(widthSpec, heightSpec);
                header.layout(0, 0, header.getMeasuredWidth(), header.getMeasuredHeight());
            }
        }
    
        @Override
        protected void dispatchDraw(Canvas canvas) {
            super.dispatchDraw(canvas);
            if (mAdapter == null || !mShouldPin || mCurrentHeader == null)
                return;
            int saveCount = canvas.save();
            canvas.translate(0, mHeaderOffset);
            canvas.clipRect(0, 0, getWidth(), mCurrentHeader.getMeasuredHeight()); // needed
            // for
            // <
            // HONEYCOMB
            mCurrentHeader.draw(canvas);
            canvas.restoreToCount(saveCount);
        }
    
        @Override
        public void setOnScrollListener(OnScrollListener l) {
            mOnScrollListener = l;
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
            mWidthMode = MeasureSpec.getMode(widthMeasureSpec);
            mHeightMode = MeasureSpec.getMode(heightMeasureSpec);
        }
    
        public void setOnItemClickListener(PinnedHeaderListView.OnItemClickListener listener) {
            super.setOnItemClickListener(listener);
        }
    
        public static abstract class OnItemClickListener implements AdapterView.OnItemClickListener {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int rawPosition, long id) {
                SectionedBaseAdapter adapter;
                if (adapterView.getAdapter().getClass().equals(HeaderViewListAdapter.class)) {
                    HeaderViewListAdapter wrapperAdapter = (HeaderViewListAdapter) adapterView.getAdapter();
                    adapter = (SectionedBaseAdapter) wrapperAdapter.getWrappedAdapter();
                } else {
                    adapter = (SectionedBaseAdapter) adapterView.getAdapter();
                }
                int section = adapter.getSectionForPosition(rawPosition);
                int position = adapter.getPositionInSectionForPosition(rawPosition);
    
                if (position == -1) {
                    onSectionClick(adapterView, view, section, id);
                } else {
                    onItemClick(adapterView, view, section, position, id);
                }
            }
    
            public abstract void onItemClick(AdapterView<?> adapterView, View view, int section, int position, long id);
    
            public abstract void onSectionClick(AdapterView<?> adapterView, View view, int section, long id);
    
        }
    }


    SectionedBaseAdapter   

    import android.util.SparseArray;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import za.co.immedia.pinnedheaderlistview.PinnedHeaderListView.PinnedSectionedHeaderAdapter;
    
    public abstract class SectionedBaseAdapter extends BaseAdapter implements PinnedSectionedHeaderAdapter {
        private static int HEADER_VIEW_TYPE = 0;
        private static int ITEM_VIEW_TYPE = 0;
    
        /**
         * Holds the calculated values of @{link getPositionInSectionForPosition}
         */
        private SparseArray<Integer> mSectionPositionCache;
        /**
         * Holds the calculated values of @{link getSectionForPosition}
         */
        private SparseArray<Integer> mSectionCache;
        /**
         * Holds the calculated values of @{link getCountForSection}
         */
        private SparseArray<Integer> mSectionCountCache;
    
        /**
         * Caches the item count
         */
        private int mCount;
        /**
         * Caches the section count
         */
        private int mSectionCount;
    
        public SectionedBaseAdapter() {
            super();
            mSectionCache = new SparseArray<Integer>();
            mSectionPositionCache = new SparseArray<Integer>();
            mSectionCountCache = new SparseArray<Integer>();
            mCount = -1;
            mSectionCount = -1;
        }
    
        @Override
        public void notifyDataSetChanged() {
            mSectionCache.clear();
            mSectionPositionCache.clear();
            mSectionCountCache.clear();
            mCount = -1;
            mSectionCount = -1;
            super.notifyDataSetChanged();
        }
    
        @Override
        public void notifyDataSetInvalidated() {
            mSectionCache.clear();
            mSectionPositionCache.clear();
            mSectionCountCache.clear();
            mCount = -1;
            mSectionCount = -1;
            super.notifyDataSetInvalidated();
        }
    
        @Override
        public final int getCount() {
            if (mCount >= 0) {
                return mCount;
            }
            int count = 0;
            for (int i = 0; i < internalGetSectionCount(); i++) {
                count += internalGetCountForSection(i);
                count++; // for the header view
            }
            mCount = count;
            return count;
        }
    
        @Override
        public final Object getItem(int position) {
            return getItem(getSectionForPosition(position), getPositionInSectionForPosition(position));
        }
    
        @Override
        public final long getItemId(int position) {
            return getItemId(getSectionForPosition(position), getPositionInSectionForPosition(position));
        }
    
        @Override
        public final View getView(int position, View convertView, ViewGroup parent) {
            if (isSectionHeader(position)) {
                return getSectionHeaderView(getSectionForPosition(position), convertView, parent);
            }
            return getItemView(getSectionForPosition(position), getPositionInSectionForPosition(position), convertView, parent);
        }
    
        @Override
        public final int getItemViewType(int position) {
            if (isSectionHeader(position)) {
                return getItemViewTypeCount() + getSectionHeaderViewType(getSectionForPosition(position));
            }
            return getItemViewType(getSectionForPosition(position), getPositionInSectionForPosition(position));
        }
    
        @Override
        public final int getViewTypeCount() {
            return getItemViewTypeCount() + getSectionHeaderViewTypeCount();
        }
    
        public final int getSectionForPosition(int position) {
            // first try to retrieve values from cache
            Integer cachedSection = mSectionCache.get(position);
            if (cachedSection != null) {
                return cachedSection;
            }
            int sectionStart = 0;
            for (int i = 0; i < internalGetSectionCount(); i++) {
                int sectionCount = internalGetCountForSection(i);
                int sectionEnd = sectionStart + sectionCount + 1;
                if (position >= sectionStart && position < sectionEnd) {
                    mSectionCache.put(position, i);
                    return i;
                }
                sectionStart = sectionEnd;
            }
            return 0;
        }
    
        public int getPositionInSectionForPosition(int position) {
            // first try to retrieve values from cache
            Integer cachedPosition = mSectionPositionCache.get(position);
            if (cachedPosition != null) {
                return cachedPosition;
            }
            int sectionStart = 0;
            for (int i = 0; i < internalGetSectionCount(); i++) {
                int sectionCount = internalGetCountForSection(i);
                int sectionEnd = sectionStart + sectionCount + 1;
                if (position >= sectionStart && position < sectionEnd) {
                    int positionInSection = position - sectionStart - 1;
                    mSectionPositionCache.put(position, positionInSection);
                    return positionInSection;
                }
                sectionStart = sectionEnd;
            }
            return 0;
        }
    
        public final boolean isSectionHeader(int position) {
            int sectionStart = 0;
            for (int i = 0; i < internalGetSectionCount(); i++) {
                if (position == sectionStart) {
                    return true;
                } else if (position < sectionStart) {
                    return false;
                }
                sectionStart += internalGetCountForSection(i) + 1;
            }
            return false;
        }
    
        public int getItemViewType(int section, int position) {
            return ITEM_VIEW_TYPE;
        }
    
        public int getItemViewTypeCount() {
            return 1;
        }
    
        public int getSectionHeaderViewType(int section) {
            return HEADER_VIEW_TYPE;
        }
    
        public int getSectionHeaderViewTypeCount() {
            return 1;
        }
    
        public abstract Object getItem(int section, int position);
    
        public abstract long getItemId(int section, int position);
    
        public abstract int getSectionCount();
    
        public abstract int getCountForSection(int section);
    
        public abstract View getItemView(int section, int position, View convertView, ViewGroup parent);
    
        public abstract View getSectionHeaderView(int section, View convertView, ViewGroup parent);
    
        private int internalGetCountForSection(int section) {
            Integer cachedSectionCount = mSectionCountCache.get(section);
            if (cachedSectionCount != null) {
                return cachedSectionCount;
            }
            int sectionCount = getCountForSection(section);
            mSectionCountCache.put(section, sectionCount);
            return sectionCount;
        }
    
        private int internalGetSectionCount() {
            if (mSectionCount >= 0) {
                return mSectionCount;
            }
            mSectionCount = getSectionCount();
            return mSectionCount;
        }
    
    }

    TestSectionedAdapter  适配器

    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import za.co.immedia.pinnedheaderlistview.SectionedBaseAdapter;
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.widget.LinearLayout;
    import android.widget.RelativeLayout;
    import android.widget.TextView;
    
    public class TestSectionedAdapter extends SectionedBaseAdapter{
    	private List<String> titles;//所有标题
    	private Map<String,List<SWWSafearea>> mMap;//根据首字母存放数据
    	
    	public TestSectionedAdapter(){
    		List<SWWSafearea> localWifi=new ArrayList<SWWSafearea>();
    		for(int i=1;i<=10;i++){
    			localWifi.add(new SWWSafearea(i,"10"+i));
    		}
    		
    		List<SWWSafearea> localGeography=new ArrayList<SWWSafearea>();
    		for(int i=4;i<=15;i++){
    			localGeography.add(new SWWSafearea(i,"10"+i,i));
    		}
    		
    		List<SWWSafearea> serverWifi=new ArrayList<SWWSafearea>();
    //		for(int i=7;i<=9;i++){
    //			serverWifi.add(new SWWSafearea(i,"10"+i));
    //		}
    		
    		List<SWWSafearea> serverGeography=new ArrayList<SWWSafearea>();
    		for(int i=30;i<=60;i++){
    			serverGeography.add(new SWWSafearea(i,"10"+i,i));
    		}
    		
    		titles=new ArrayList<String>();
    		titles.add("1");
    		titles.add("2");
    		titles.add("3");
    		titles.add("4");
    		
    		mMap = new HashMap<String, List<SWWSafearea>>();
    		mMap.put(titles.get(0),localWifi);
    		mMap.put(titles.get(1),localGeography);
    		mMap.put(titles.get(2),serverWifi);
    		mMap.put(titles.get(3),serverGeography);
    	}
    
        @Override
        public Object getItem(int section, int position) {
            return mMap.get(titles.get(section)).get(position);
        }
    
        @Override
        public long getItemId(int section, int position) {
            return 0;
        }
    
        @Override
        public int getSectionCount() {//一共显示多少行标题栏
            return titles.size();
        }
    
        //每列显示的行数
        @Override
        public int getCountForSection(int section) {
            return mMap.get(titles.get(section)).size();
        }
    
    	@Override
        public View getItemView(final int section,final int position, View convertView, ViewGroup parent) {
    		ViewHolder holder=null;
    		if (null==convertView) {
    			holder=new ViewHolder();
    			LayoutInflater inflator = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    			convertView=(LinearLayout)inflator.inflate(R.layout.list_item, null);
    			holder.name=(TextView) convertView.findViewById(R.id.name);
    			holder.radius=(TextView) convertView.findViewById(R.id.radius);
    			holder.safeareaItem=(RelativeLayout) convertView.findViewById(R.id.safearea_item);
    			convertView.setTag(holder);
    		}else{
    			holder=(ViewHolder) convertView.getTag();
    		}
    		SWWSafearea sf=mMap.get(titles.get(section)).get(position);
    		if(section==0||section==2){
    			holder.name.setText(sf.name);
    			holder.radius.setText("");
    		}else{
    			holder.name.setText(sf.name);
    			holder.radius.setText(""+sf.radius);
    		}
    		holder.safeareaItem.setOnClickListener(new OnClickListener() {
    			@Override
    			public void onClick(View v) {
    				mMap.get(titles.get(section)).remove(position);
    				notifyDataSetChanged();
    			}
    		});
            return convertView;
        }
        
    	private class ViewHolder{
    		TextView name,radius;
    		RelativeLayout safeareaItem;
    	}
    
        @Override
        public View getSectionHeaderView(int section, View convertView, ViewGroup parent) {
            LinearLayout layout = null;
            if (convertView == null) {
                LayoutInflater inflator = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                layout = (LinearLayout) inflator.inflate(R.layout.header_item, null);
            } else {
                layout = (LinearLayout) convertView;
            }
            
            TextView textView=((TextView) layout.findViewById(R.id.textItem));
            if(mMap.get(titles.get(section)).size()>0){
            	textView.setVisibility(View.VISIBLE);
            	textView.setText(titles.get(section));
            }else{
            	textView.setVisibility(View.GONE);
            }
            return layout;
        }
        
        
    
    	//实体类
    	private class SWWSafearea{
    		public int id;
    		public String name;
    		public int radius;
    		public SWWSafearea(int id, String name, int radius) {
    			super();
    			this.id = id;
    			this.name = name;
    			this.radius = radius;
    		}
    		
    		public SWWSafearea(int id, String name) {
    			super();
    			this.id = id;
    			this.name = name;
    		}
    	}
    }

    MainActivity 

    import android.app.Activity;
    import android.os.Bundle;
    import android.view.Menu;
    import za.co.immedia.pinnedheaderlistview.PinnedHeaderListView;
    
    public class MainActivity extends Activity {
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            PinnedHeaderListView listView = (PinnedHeaderListView) findViewById(R.id.pinnedListView);
            
            TestSectionedAdapter sectionedAdapter = new TestSectionedAdapter();
            listView.setAdapter(sectionedAdapter);
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            getMenuInflater().inflate(R.menu.activity_main, menu);
            return true;
        }
    }

    效果图如下:



    推荐下自己创建的android QQ群:202928390   欢迎大家的加入.

    源码下载地址



  • 相关阅读:
    spi详解
    spi协议
    C语言break,return
    通信协议
    传输层
    网络层
    数据链路层
    物理层
    无线通信
    cpu设计过程
  • 原文地址:https://www.cnblogs.com/yishaochu/p/5078641.html
Copyright © 2011-2022 走看看