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 ...
随机推荐
- MVC框架
MVC (Modal View Controler)本来是存在于Desktop程序中的,M是指数据模型,V是指用户界面,C则是控制器.使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用 ...
- gulp使用配置
gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也非常简单,学习起来很容易,而且gulpjs使用的是nodejs中stream来读取和操作数据,其速 ...
- webstorm2016注册码
43B4A73YYJ-eyJsaWNlbnNlSWQiOiI0M0I0QTczWVlKIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYXNzaWduZWVOYW1lIjoiI ...
- Linux软件安装
#配置/etc/apt/sources.list 通过root权限修改/etc/apt/sources.list $ su #输入密码进入root权限 $ chmod 0666 /etc/apt/so ...
- mongoose 和 mongoDB
第三方学习地址:http://blog.csdn.net/foruok/article/details/47746057 下载mongoDB https://www.mongodb.com/downl ...
- 非常棒的Android对话框效果
FlycoDialog_Master http://www.see-source.com/androidwidget/detail.html?wid=488 带有各种动画效果的弹出对话框控件.你也可以 ...
- 谢欣伦 - OpenDev原创教程 - 蓝牙设备查找类CxBthRadio & CxBthRadioFind
这是一个精练的蓝牙设备查找类,类名.函数名和变量名均采用匈牙利命名法.小写的x代表我的姓氏首字母(谢欣伦),个人习惯而已,如有雷同,纯属巧合. CxBthRadioFind的使用如下: void CU ...
- 在iOS中使用ZXing库[转]
前言 ZXing(Github镜像地址)是一个开源的条码生成和扫描库(开源协议为Apache2.0).它不但支持众多的条码格式,而且有各种语言的实现版本,它支持的语言包括:Java, C++, C#, ...
- 单元测试模拟框架:Nsubstitute
Nsubstitute是一个开源的框架,源码是C#实现的.你可以在这里获得它的源码:https://github.com/nsubstitute/NSubstitute NSubstitut ...
- MVC学习二:基础语法
目录 一:重载方法的调用 二:数据的传递 三:生成控件 四:显示加载视图 五:强类型视图 六:@Response.Write() 和 @Html.Raw()区别 七:视图中字符串的输入 八:模板页 一 ...