ListView 节头制作

    主要用到了稀疏数组,SparseArray是 Android框架独有的类,在标准的JDK中不存在这个类。它要比 HashMap 节省内存,某些情况下比HashMap性能更好,而且不会进行自动装箱操作。
制作listview节头主要是通过自定系adapter结合SparseArray来完成,将每一个分类都当成一个列表存储在系数数组中,其类似与多为数组,其中只在关键节点上存储节头,节头下的内容由每一小节自行管理。显示效果如下:

ListView 节头制作_第1张图片

代码如下:

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 indexth 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]; }

你可能感兴趣的:(android)