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
欢迎大家的加入.
PinnedHeaderListView实现删除的更多相关文章
- Android SwipeActionAdapter结合Pinnedheaderlistview实现复杂列表的左右滑动操作
在上一篇博客<Android 使用SwipeActionAdapter开源库实现简单列表的左右滑动操作>里,已经介绍了利用SwipeActionAdapter来左右滑动操作列表: 然,有时 ...
- "无法删除数据库,因为该数据库当前正在使用"问题解决
异常处理汇总-数据库系列 http://www.cnblogs.com/dunitian/p/4522990.html 以前刚学数据库的时候比较苦恼这个问题,今天删除的时候又看见了,正好一起记录一下 ...
- php批量删除
php批量删除可以实现多条或者全部数据一起删除 新建php文件 显示数据库中内容: <table width="100%" border="1" cell ...
- linux centos中添加删除修改环境变量,设置java环境变量
前言 安装完软件必要添加环境变量.指令很少,然而长时间不写就会不自信:我写的对吗?于是百度开始,于是发现又是各有千秋.好吧,好记星不如烂笔头.当然,最重要的是,百度出来的都他妈的是如何添加环境变量,只 ...
- ASP.NET MVC一次删除多笔记录
批量删除数据记录,如下面的截屏: 先选中想删除的记录,然后点一下删除铵钮,系统将把选中的记录一次性删除.在此,Insus.NET不想每删除一笔记录连接一次数据库. 因此需要把选择的记录一次上传至服务器 ...
- 如何区别数据库删除语句drop与delete与truncate?
1.delete:删除数据表中的行(可以删除某一行,也可以在不删除数据表的情况下删除所有行) 删除某一行:delete from 数据表名称 where 列名称=值: 删除所有行:delete*fro ...
- sql 删除表中的重复记录
嗯,遇见了表中存在重复的记录的问题,直接写sql删除时最快的,才不要慢慢的复制到excel表中慢慢的人工找呢.哼. 如下sql,找出重复的记录,和重复记录中ID值最小的记录(表中ID为自增长) sel ...
- ORACLE从共享池删除指定SQL的执行计划
Oracle 11g在DBMS_SHARED_POOL包中引入了一个名为PURGE的新存储过程,用于从对象库缓存中刷新特定对象,例如游标,包,序列,触发器等.也就是说可以删除.清理特定SQL的执行计划 ...
- mysql删除重复记录语句的方法
例如: id name value 1 a pp 2 a pp 3 b iii 4 b pp 5 b pp 6 c pp 7 c pp 8 c iii id是主键 要求得到这样的结果 id name ...
随机推荐
- 获取文件Md5值
private static string GetFileMD5(string filePath) { string _md5Value = string.Empty; try { if (Syste ...
- Django动态渲染多层菜单
为后续给菜单设置权限管理方便,通过给页面模版菜单动态渲染,通过数据菜单表进行匹配需要渲染的菜单 #Django表结构 class Menus(models.Model): name = models. ...
- 【Postgresql】数据库函数
1.Postgresql查询前几条记录的SQL语句 select * from table where ...... LIMIT N ; 2.SQL limit integer offset int ...
- C#委托与事件初探
最近刚刚接触C#,学到事件与委托部分无法理解,于是上网查阅了各种资料,终于明白了一些,在此进行总结. 一.C语言中的函数指针 想要理解什么是委托,就要先理解函数指针的概念.所谓函数指针,就是指向函数的 ...
- sublime Text 3 字体
1,Comic Sans Ms 2,DejaVu Sans Mono 3,microsoft yahei(微软雅黑) 4,Microsoft Yahei UI(微软雅黑增强版) 5,Ubuntu Mo ...
- [LintCode] Container With Most Water 装最多水的容器
Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). ...
- 有关JVM配置参数含义
1.参数的含义-vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M-vmargs 说明后面是VM的参数,所以后面的其实都是JV ...
- lua中基类和“继承机制”
基类:基类定义了所有对于派生类来说普通的属性和方法,派生类从基类继承所需的属性和方法,且在派生类中增加新的属性和方法. 继承:继承是C++语言的一种重要机制,它允许在已定义的类的基础上产生新类. lu ...
- 安卓初級教程(4):sqlite建立資料庫
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 ...
- UI控件(UITextView)
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //UITextView与UITextField主要 ...