ListView 右侧导航
2016-01-08 14:16
162 查看
src 中的 MainActivity:
public class MainActivity extends Activity implements OnItemClickListener { /** * 显示城市列表的ListView控件 */ private ListView lvCityList; /** * 显示城市列表的ListView的数据源 */ private List<City> cityList; /** * 显示城市列表的ListView的Adapter */ private CityAdapter cityAdapter; /** * 显示右侧字母导航的ListView控件 */ private ListView lvSideBar; /** * 显示右侧字母导航的ListView的数据源 */ private List<String> sortKeys; /** * 显示右侧字母导航的ListView的Adapter */ private SideBarAdapter sideBarAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化ListView lvCityList = (ListView) findViewById(R.id.lv_city_list); // 获取数据源 cityList = getCityListData(); // 对城市列表排序 sortCityListByPinyin(cityList); // 创建adapter cityAdapter = new CityAdapter(this, cityList); // 为ListView配置adapter lvCityList.setAdapter(cityAdapter); // 初始化右侧字母导航的ListView lvSideBar = (ListView) findViewById(R.id.lv_side_bar); // 获取数据源 sortKeys = getSideBarData(); // 创建adapter sideBarAdapter = new SideBarAdapter(this, sortKeys); // 为ListView配置adapter lvSideBar.setAdapter(sideBarAdapter); // 为ListView配置Item点击监听器 lvSideBar.setOnItemClickListener(this); } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // 根据poisiton获取被点击的字母 String str = sortKeys.get(position); // 把点击的字母转换成char类型 char ch = str.charAt(0); // 获取该字母在城市列表中出现的位置 int moveToPosition = cityAdapter.getPositionForSection(ch); // 城市列表的ListView快速移动到指定位置 if(moveToPosition != -1) { lvCityList.setSelection(moveToPosition); } } /** * 根据拼音将城市列表排序 */ private void sortCityListByPinyin(List<City> data) { Collections.sort(data, new Comparator<City>() { @Override public int compare(City lhs, City rhs) { return lhs.getPinyin().compareTo(rhs.getPinyin()); } }); } /** * 获取城市列表的数据源 * * @return 城市列表的数据源 */ private List<City> getCityListData() { List<City> data = new ArrayList<City>(); data.add(new City("北京", "beijing")); data.add(new City("上海", "shanghai")); data.add(new City("广州", "guangzhou")); data.add(new City("深圳", "shenzhen")); data.add(new City("成都", "chengdu")); data.add(new City("重庆", "chongqing")); data.add(new City("大连", "dalian")); data.add(new City("厦门", "xiamen")); data.add(new City("丽江", "lijiang")); data.add(new City("三亚", "sanya")); data.add(new City("青岛", "qingdao")); data.add(new City("铁岭", "tieling")); data.add(new City("攀枝花", "panzhihua")); data.add(new City("杭州", "hangzhou")); data.add(new City("苏州", "suzhou")); data.add(new City("南京", "nanjing")); data.add(new City("武汉", "wuhan")); data.add(new City("哈尔滨", "haerbin")); return data; } /** * 获取右侧字母导航的数据源 * * @return 右侧字母导航的数据源 */ private List<String> getSideBarData() { List<String> data = new ArrayList<String>(); // 根据CityAdapter中的getSections()获取所有应该显示的首字母 String[] arr = (String[]) cityAdapter.getSections(); // 对数组进行排序 Arrays.sort(arr); // 将数组转换成List data = Arrays.asList(arr); return data; } }
src 中的 SideBarAdapter:public class SideBarAdapter extends BaseAdapter {
private Context context;
private List<String> data;
private LayoutInflater inflater;
public SideBarAdapter(Context context, List<String> data) {
super();
this.context = context;
this.setData(data);
inflater = LayoutInflater.from(this.context);
}
public void setData(List<String> data) {
if (data == null) {
data = new ArrayList<String>();
}
this.data = data;
}
@Override
public int getCount() {
return data.size();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.side_bar_item, null);
holder.tvSortKey = (TextView) convertView.findViewById(R.id.tv_side_bar_item_sort_key);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tvSortKey.setText(data.get(position));
return convertView;
}
private class ViewHolder {
TextView tvSortKey;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
}
src 中的 CityAdapter:
public class CityAdapter extends BaseAdapter implements SectionIndexer { /** * 上下文对象 */ private Context context; /** * 数据源 */ private List<City> data; /** * 将XML布局加载为View对象的工具 */ private LayoutInflater inflater; /** * 构造方法 * * @param context * 上下文对象 * @param data * 数据源 */ public CityAdapter(Context context, List<City> data) { super(); this.context = context; this.setData(data); inflater = LayoutInflater.from(this.context); } /** * 设置数据源 * * @param data * 数据源 */ public void setData(List<City> data) { if (data == null) { data = new ArrayList<City>(); } this.data = data; } @Override public int getCount() { return data.size(); } // private String lastSortKey; @Override public View getView(int position, View convertView, ViewGroup parent) { // 准备ViewHolder ViewHolder holder; // 判断convertView参数是否为空 if (convertView == null) { // 当convertView为空时,需要根据布局进行加载,并创建ViewHolder,完成初始化,将ViewHolder封装到convertView,以至于重用convertView时,可以直接获取ViewHolder holder = new ViewHolder(); convertView = inflater.inflate(R.layout.city_item, null); holder.tvCitySortKey = (TextView) convertView .findViewById(R.id.tv_city_sort_key); holder.tvCityName = (TextView) convertView .findViewById(R.id.tv_city_name); convertView.setTag(holder); } else { // 当convertView不为空时,则表示它是被系统自动重用的,则它内部的控件也是重用的 holder = (ViewHolder) convertView.getTag(); } // 获取当前需要显示的数据 City city = data.get(position); if(position == getPositionForSection(getSectionForPosition(position))) { // 当前位置与“根据位置找到的section,然后根据section找到应该出现的位置”相等,则显示section holder.tvCitySortKey.setVisibility(View.VISIBLE); } else { // position与section出现的position不相等,则不显示 holder.tvCitySortKey.setVisibility(View.GONE); } // // 获取当前的sort key // String currentSortKey = city.getPinyin().toUpperCase(Locale.CHINA) // .substring(0, 1); // // 对比是否与上一条相同,且必须是position > 0时进行对比(第1条记录不需要对比) // if(position > 0 && currentSortKey.equals( // data.get(position - 1) // .getPinyin(). // toUpperCase(Locale.CHINA) // .substring(0, 1))) { // // 相同,隐藏 // holder.tvCitySortKey.setVisibility(View.GONE); // } else { // // 不同,显示 // holder.tvCitySortKey.setVisibility(View.VISIBLE); // } // 设置控件的显示 holder.tvCitySortKey.setText("" + ((char)getSectionForPosition(position))); holder.tvCityName.setText(city.getName()); // 返回 return convertView; } private class ViewHolder { TextView tvCitySortKey, tvCityName; } @Override public int getPositionForSection(int section) { int currentSection; for (int i = 0; i < data.size(); i++) { // 找到当次循环到的城市数据的section currentSection = getSectionForPosition(i); // 判断当次的section是否与参数section匹配 // 如果匹配,则当前循环的次数就是所需要的position,且跳出循环 if(currentSection == section) { return i; } } return -1; } @Override public int getSectionForPosition(int position) { return data.get(position).getPinyin().toUpperCase(Locale.CHINA).charAt(0); } // 以下抽象方法可以不具体实现 @Override public Object getItem(int position) { // TODO Auto-generated method stub return null; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return 0; } @Override public Object[] getSections() { // 基于Set容器内部数据的唯一性,先使用Set保存所有数据对应的首字母 Set<String> set = new HashSet<String>(); for (int i = 0; i < data.size( a47d ); i++) { set.add("" + ((char)getSectionForPosition(i))); } Log.d("", "section count -> " + set.size()); // 根据Set的大小创建数组 String[] arr = new String[set.size()]; // 循环整个Set,把每个元素添加到数组 int i = 0; for (String string : set) { Log.d("", "set string -> " + string); arr[i] = string; Log.d("", "arr[" + i + "]" + arr[i]); i++; } // 返回 return arr; } }
src 中的 City:public class City {
private String name;
private String pinyin;
public City() {
super();
}
public City(String name, String pinyin) {
super();
this.name = name;
this.pinyin = pinyin;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPinyin() {
return pinyin;
}
public void setPinyin(String pinyin) {
this.pinyin = pinyin;
}
}layout 中的 activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <ListView android:id="@+id/lv_city_list" android:layout_width="match_parent" android:layout_height="match_parent" /> <ListView android:id="@+id/lv_side_bar" android:layout_width="20dp" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:divider="@null" > </ListView> </RelativeLayout>layout 中的 city_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/tv_city_sort_key"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#cccccc"
android:paddingBottom="2dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingTop="2dp"
android:text="C"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_city_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_city_sort_key"
android:paddingBottom="5dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="5dp"
android:text="成都"
android:textSize="16sp" />
</RelativeLayout>layout 中的 side_bar_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/tv_side_bar_item_sort_key"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textSize="12sp"
android:text="A" />
</RelativeLayout>
相关文章推荐
- 通过编写Shell、Python脚本来实现在线管理KVM虚拟机
- UIWebView设置图片的宽度适应屏幕的大小
- 如何下载谷歌地球高程数据为DEM
- {Unity} 平台预定义
- storm 入门原理介绍
- CGBitmapContextCreate函数
- js判断当前的访问是手机/电脑
- cocos2d-x scoket 解决方案
- Java 密码扩展无限制权限策略文件
- 指针 p238
- 微信图文美化编辑器试试构思编辑器
- 使用HTML CSS实现网页换肤效果(二)
- 秋农家常菜——老干妈蒜香土豆丝and秘制炝炒莴笋叶
- Android 软键盘和emoji表情切换方案,和微信几乎一样的体验
- XMPP介绍二:Core Data
- Xcode描述文件路径
- Linux 查看线程占用情况
- c++ concurrent progamming(2) thread manage
- CDI技术第七步 生命周期管理
- iOS获取时间戳,字典转换成json数据