android 开发技巧(15)--为ListView添加分段标头

来源:互联网 发布:linux服务器开启ping 编辑:程序博客网 时间:2024/05/22 07:26

效果图:这里写图片描述
我记得github上有一个类似的效果github类似效果

说一下实现这个效果的思路:在列表项中嵌入分段标头,然后根据需要显示或者隐藏分段标头,创建一个特殊的TextView,让其叠加在列表的顶部,当列表滚动到一个新的分段时,就更新其内容

创建列表布局
创建一个xml,随列表滚动的分段标头和列表顶部的固定分段标头复用这个布局文件
header.xml

<?xml version="1.0" encoding="utf-8"?><TextView xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/header"    style="@android:style/TextAppearance.Small"    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:background="#0000ff" />

主布局list.xml

<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent" >    <ListView        android:id="@android:id/list"        android:layout_width="fill_parent"        android:layout_height="fill_parent" />    <include layout="@layout/header" /></FrameLayout>

创建列表项布局文件list_item.xml,包含数据项和分段标头

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:orientation="vertical" >    <include layout="@layout/header" />    <TextView        android:id="@+id/label"        style="@android:style/TextAppearance.Large"        android:layout_width="fill_parent"        android:layout_height="wrap_content" /></LinearLayout>

SectionAdapter.java

public class SectionAdapter extends ArrayAdapter<String> {  private Activity activity;  public SectionAdapter(Activity activity, String[] objects) {    super(activity, R.layout.list_item, R.id.label, objects);//为自定义视图指定XML布局文件    this.activity = activity;  }  @Override  public View getView(int position, View view, ViewGroup parent) {    if (view == null) {      view = activity.getLayoutInflater().inflate(R.layout.list_item,          parent, false);    }    TextView header = (TextView) view.findViewById(R.id.header);    String label = getItem(position);    if (position == 0//检查列表项起始字母是否发生了改变,如果发生改变,该列表项就是分段中的第一项,修改分段标头的内容并显示该分段标头,否则隐藏        || getItem(position - 1).charAt(0) != label.charAt(0)) {      header.setVisibility(View.VISIBLE);      header.setText(label.substring(0, 1));    } else {      header.setVisibility(View.GONE);//隐藏分段标头    }    return super.getView(position, view, parent);  }}

主界面

public class Hack26Activity  extends ListActivity {    private TextView topHeader;//用于访问分段标头    private int topVisiblePosition = -1;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.list);        topHeader = (TextView) findViewById(R.id.header);        setListAdapter(new SectionAdapter(this, Countries.COUNTRIES));        //设置滚动监听器,当用户滚动列表时,检查位置是否发生了变化,如果改变,调用setTopHeader更新悬浮的分段标头,当列表第一次显示时,确保根据第一个列表项初始化分段标头        getListView().setOnScrollListener(                new AbsListView.OnScrollListener() {                    @Override                    public void onScrollStateChanged(AbsListView view,                                                     int scrollState) {                        // Empty.                    }                    @Override                    public void onScroll(AbsListView view, int firstVisibleItem,                                         int visibleItemCount, int totalItemCount) {                        if (firstVisibleItem != topVisiblePosition) {                            topVisiblePosition = firstVisibleItem;                            setTopHeader(firstVisibleItem);                        }                    }                });        setTopHeader(0);    }    private void setTopHeader(int pos) {        final String text = Countries.COUNTRIES[pos].substring(0, 1);        topHeader.setText(text);//更新文本内容    }}
0 0