主要用到了稀疏数组,SparseArray是 Android框架独有的类,在标准的JDK中不存在这个类。它要比 HashMap 节省内存,某些情况下比HashMap性能更好,而且不会进行自动装箱操作。
制作listview节头主要是通过自定系adapter结合SparseArray来完成,将每一个分类都当成一个列表存储在系数数组中,其类似与多为数组,其中只在关键节点上存储节头,节头下的内容由每一小节自行管理。显示效果如下:
代码如下:
package com.example.mhyuam.listtviewheader;
import android.util.Log;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
/**
* Created by mhyuam on 2016/7/10.
*/
abstract class MyAdapter extends BaseAdapter implements AdapterView.OnItemClickListener{
private static final int TYPE_HEAD = 1;
private static final int TYPE_ITEM = 2;
private LayoutInflater layoutInflater;
private int HEADER_RES,ITEM_RES;
private List sections;
private SparseArray keySctions;
MyAdapter(ListView listView,int HEADER_RES,int ITEM_RES){
layoutInflater = LayoutInflater.from(listView.getContext());
this.HEADER_RES = HEADER_RES;
this.ITEM_RES = ITEM_RES;
sections = new ArrayList();
keySctions = new SparseArray();
listView.setOnItemClickListener(this);
}
public void addSections(String title,String[] array){
Section item = new Section(title,array);
int index = sections.indexOf(item);
if(index >= 0){
sections.remove(index);
sections.add(index,item);
}else {
sections.add(item);
}
reOrder();
notifyDataSetChanged();
}
private void reOrder(){
keySctions.clear();
int startPosition = 0;
for (Section item:sections) {
keySctions.put(startPosition,item);
startPosition +=item.getCount();
}
}
@Override
public int getCount() {
int count = 0;
for (Section item:sections){
count += item.getCount();
}
return count;
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public int getItemViewType(int position) {
Log.i("123","getItemViewType position = " +position);
if (isHeaderAtPosition(position)){
return TYPE_HEAD;
}else {
return TYPE_ITEM;
}
//Log.i("123","getItemViewType position = " +position);
//return position;
}
private boolean isHeaderAtPosition(int position) {
for (int i=0; i < keySctions.size(); i++) {
//If this position is a key value, it's a header position
if (position == keySctions.keyAt(i)) {
Log.i("123","---------i = ------- "+i+" -----position---- = "+position +" ---- keySctions = "+keySctions.get(i));
return true;
}
}
return false;
}
@Override
public Object getItem(int position) {
return findSectionItemAtPosition(position);
}
private Object findSectionItemAtPosition(int position){
int firstpsition,lastposition;
for (int i = 0;iif (position >= firstpsition && position < lastposition){
int sectionposition = position - firstpsition -1;
return keySctions.valueAt(i).getItem(sectionposition);
}
}
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View view, ViewGroup viewGroup) {
switch (getItemViewType(position)) {
case TYPE_HEAD:
return getHeaderView(position,view,viewGroup);
case TYPE_ITEM:
return getItemView(position,view,viewGroup);
default:
return view;
}
}
@Override
public boolean isEnabled(int position) {
return !isHeaderAtPosition(position);
}
public View getHeaderView(int position,View view,ViewGroup viewGroup){
if(view == null){
view = layoutInflater.inflate(HEADER_RES,viewGroup,false);
}
Section item = keySctions.get(position);
TextView tv = (TextView) view.findViewById(R.id.text1);
tv.setText(item.getTitle());
return view;
}
public View getItemView(int position,View view,ViewGroup viewGroup){
if(view == null){
view = layoutInflater.inflate(ITEM_RES,viewGroup,false);
}
Object item = findSectionItemAtPosition(position);
TextView tv = (TextView) view.findViewById(android.R.id.text1);
tv.setText(item.toString());
return view;
}
@Override
public void onItemClick(AdapterView> adapterView, View view, int position, long l) {
Object item = findSectionItemAtPosition(position);
if (item != null){
ItemClick(item);
}
}
abstract void ItemClick(Object item);
}
package com.example.mhyuam.listtviewheader;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ListView;
public class ListHeader extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ListView listView = new ListView(this);
MyAdapter adapter = new MyAdapter(listView,R.layout.header_layout,android.R.layout.simple_list_item_1) {
@Override
void ItemClick(Object item) {
Log.i("123","您选择了" + item.toString());
}
};
adapter.addSections("水果" ,new String[]{"苹果","香蕉","橘子"});
adapter.addSections("蔬菜" ,new String[]{"白菜","萝卜","黄瓜","西红柿"});
adapter.addSections("肉类" ,new String[]{"猪肉","牛肉"});
listView.setAdapter(adapter);
setContentView(listView);
}
}
package com.example.mhyuam.listtviewheader;
/**
* Created by mhyuam on 2016/7/10.
*/
public class Section {
private String title;
private String[] list;
public Section(String title,String[] list){
this.title = title;
this.list = list;
}
public String getTitle(){
return title;
}
public String getItem(int posiion){
return list[posiion];
}
public int getCount(){
return list == null?1:list.length +1;
}
public boolean equals(Object object){
if((object != null) && (object instanceof Section)){
return ((Section) object).getTitle().equals(title);
}
return false;
}
}
note: SparseArray有类似于HashMap或者多维数组的性质,其脚标问题十分关键,一不注意就有可能搞错,且不便排查,如果在使用出现了莫名其妙的问题,那可能是脚标那里出错了。同时也要注意 SparseArray.get(index)以及SparseArray.value(index)的差别。
/**
* Gets the Object mapped from the specified key, or null
* if no such mapping has been made.
*/
public E get(int key) {
return get(key, null);
}
/**
* Given an index in the range 0...size()-1
, returns
* the value from the index
th key-value mapping that this
* SparseArray stores.
*
* The values corresponding to indices in ascending order are guaranteed
* to be associated with keys in ascending order, e.g.,
* valueAt(0)
will return the value associated with the
* smallest key and valueAt(size()-1)
will return the value
* associated with the largest key.
*/
@SuppressWarnings("unchecked")
public E valueAt(int index) {
if (mGarbage) {
gc();
}
return (E) mValues[index];
}