上篇博客,根据几位大神的博客总结出了一篇ListView悬浮,快速索引。效果非常不错,而且易于扩展,可在实际项目中并不是很通用,因为总需要实现SectionIndexer接口,比较复杂而且不是所有的分且头部都是由A-Z 这种分组,也可能是以任意条件的分组,比如时间。这种情况下上一篇的方法就不能用了。本篇则是基于上一篇的代码修改,使的ListView不再去实现SectionIndexer.修改OnScrollListener中的监听,使得可悬浮ListView能够基本通用。
效果与上篇完全一样。
代码如下:
1.adapter代码
/**
* @description 通用Adapter
* @author rzq
* @date 2015
*/
public class SortAdapter extends BaseAdapter
{
private List<SortModel> list = null;
private Context mContext;
private SortModel country;
private ViewHolder holder1, holder2;
public SortAdapter(Context mContext, List<SortModel> list)
{
this.mContext = mContext;
this.list = list;
}
@Override
public int getCount()
{
return list.size();
}
@Override
public Object getItem(int position)
{
return list.get(position);
}
@Override
public long getItemId(int position)
{
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
country = (SortModel) list.get(position);
int type = getItemViewType(position);
if (convertView == null)
{
switch (type)
{
case 0:
holder1 = new ViewHolder();
convertView = LayoutInflater.from(mContext).inflate(R.layout.item_group, parent, false);
holder1.tvTitle = (TextView) convertView.findViewById(R.id.catalog);
convertView.setTag(holder1);
break;
case 1:
holder2 = new ViewHolder();
convertView = LayoutInflater.from(mContext).inflate(R.layout.item, parent, false);
holder2.tvTitle = (TextView) convertView.findViewById(R.id.title);
convertView.setTag(holder2);
break;
}
}
else
{
switch (type)
{
case 0:
holder1 = (ViewHolder) convertView.getTag();
break;
case 1:
holder2 = (ViewHolder) convertView.getTag();
break;
}
}
switch (type)
{
case 0:
holder1.tvTitle.setText(country.getSortLetters());
break;
case 1:
holder2.tvTitle.setText(country.getName());
break;
}
return convertView;
}
@Override
public int getItemViewType(int position)
{
country = (SortModel) getItem(position);
if (country.isGroup())
{
return 0;
}
else
{
return 1;
}
}
@Override
public int getViewTypeCount()
{
return 2;
}
final static class ViewHolder
{
TextView tvTitle;
}
}
上述代码是一个最普通的多布局Adapter写法,无需实现SectionIndex.
2.Activity代码:
public class MainActivity extends Activity
{
private ListView sortListView;
private SortAdapter adapter;
private CharacterParser characterParser;
private List<SortModel> SourceDateList;
private PinyinComparator pinyinComparator;
private LinearLayout titleLayout;
private TextView title;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
}
private void initViews()
{
titleLayout = (LinearLayout) findViewById(R.id.title_layout);
title = (TextView) findViewById(R.id.title);
characterParser = CharacterParser.getInstance();
pinyinComparator = new PinyinComparator();
sortListView = (ListView) findViewById(R.id.country_lvcountry);
SourceDateList = filledData(getResources().getStringArray(R.array.date));
Collections.sort(SourceDateList, pinyinComparator);
adapter = new SortAdapter(this, SourceDateList);
sortListView.setAdapter(adapter);
sortListView.setOnScrollListener(new OnScrollListener()
{
@Override
public void onScrollStateChanged(AbsListView view, int scrollState)
{
}
/**
* AbsListView滑动时执行
*/
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
/**
* 取出列表相临两项
*/
SortModel modelFirst = (SortModel) adapter.getItem(firstVisibleItem);
SortModel modelSecond = (SortModel) adapter.getItem(firstVisibleItem + 1);
if (firstVisibleItem != lastFirstVisibleItem)
{
MarginLayoutParams params = (MarginLayoutParams) titleLayout.getLayoutParams();
params.topMargin = 0;
titleLayout.setLayoutParams(params);
if (modelFirst.getSortLetters() != null)
{
title.setText(modelFirst.getSortLetters());
}
}
/**
* 相临两组Data状态不同,且第一组数据的状态为普 通数据,第二组数据为Group,则符合悬浮的条件,开始进行判断部悬浮计算
*/
if (modelFirst.isGroup() == false && modelSecond.isGroup() == true)
{
View childView = view.getChildAt(1);
if (childView != null)
{
int titleHeight = titleLayout.getHeight();
int top = childView.getTop();
MarginLayoutParams params = (MarginLayoutParams) titleLayout.getLayoutParams();
if (top <= titleHeight)
{
float pushedDistance = -(titleHeight - top);
params.topMargin = (int) pushedDistance;
titleLayout.setLayoutParams(params);
}
}
}
lastFirstVisibleItem = firstVisibleItem;
}
});
}
private int lastFirstVisibleItem = -1;
private List<SortModel> filledData(String[] date)
{
List<SortModel> mSortList = new ArrayList<SortModel>();
for (int i = 0; i < date.length; i++)
{
SortModel sortModel = new SortModel();
sortModel.setName(date[i]);
/**
* 添加了Group数据,[A-Z]
*/
if (date[i].matches("[A-Z]"))
{
sortModel.setSortLetters(date[i]);
sortModel.setGroup(true);
}
else
{
String pinyin = characterParser.getSelling(date[i]);
String sortString = pinyin.substring(0, 1).toUpperCase();
if (sortString.matches("[A-Z]"))
{
sortModel.setSortLetters(sortString.toUpperCase());
}
else
{
sortModel.setSortLetters("#");
}
sortModel.setGroup(false);
}
mSortList.add(sortModel);
}
return mSortList;
}
}
通过上述代码可以看出,通过这訲方式实现的效果更加的通用,也是在研究了多位大神的博客后,自己有了改进的想法,编码实现了自己的想法。使用这訲不重写ListView的方式,我们还可以结合PullToRefresh做上下拉刷新,而如果你重定义ListView则很难再与其它开源库相结合。这是使用这一方式最大的优势。