【Android】城市列表,字母吸顶
16lz
2021-01-23
效果动图:
(后面补上)
总体布局:
<?xml version="1.0" encoding="utf-8"?>
Fragment中实现:
listCitylist = (ListView) mView.findViewById(R.id.list_citylist);listCitylist.addHeaderView(headerView);listCitylist.setOnScrollListener(onScrollListener);
/** * 城市列表适配 */ private void setCityListAdapter() { if (null == cityListAdapter) { cityListAdapter = new CityListAdapter(getActivity(), cityListDatas); listCitylist.setAdapter(cityListAdapter); }else { //第二次进入城市列表的时候,list和adapter实例还在,但是list和adapter失去关联,所以要重新绑定 listCitylist.setAdapter(cityListAdapter); cityListAdapter.updateData(cityListDatas); } cityListAdapter.setOnCityListClickListener(onCityListItemClickListener); zMIndex = cityListAdapter.getzMIndexs(); letter.bringToFront(); }
/** * 城市列表点击事件 */ private CityListAdapter.OnCityListItemClickListener onCityListItemClickListener = new CityListAdapter.OnCityListItemClickListener() { @Override public void onCityListClickListener(View v) { CityInfo c = (CityInfo) v.getTag(); ((CommunityManagerActivityNew)getActivity()).formCityListToSelectComm(c.name, c.code); } };
/** * 城市列表滑动监听,控制字母吸顶 */ AbsListView.OnScrollListener onScrollListener = new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { switch (scrollState) { case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL://拖动 case AbsListView.OnScrollListener.SCROLL_STATE_FLING://惯性滑动 // 显示滑动时屏幕可见条目中离标题栏最近的第一行 int position = listCitylist.getFirstVisiblePosition(); //由于listview添加了一个header,所以position=0代表的是header //这里获取到的position和下面onscroll方法里的firstVisibleItem值一致 break; case AbsListView.OnScrollListener.SCROLL_STATE_IDLE://手指离开或者惯性滑动停止 break; } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (firstVisibleItem > 0) { topTitle.setVisibility(View.VISIBLE); topTitle.bringToFront(); if(firstVisibleItem >= zMIndex[25] + 1 && zMIndex[25] != 0) { topTitle.setText(letters[25]); }else if(firstVisibleItem >= zMIndex[24] + 1 && zMIndex[24] != 0) { topTitle.setText(letters[24]); }else if(firstVisibleItem >= zMIndex[23] + 1 && zMIndex[23] != 0) { topTitle.setText(letters[23]); }else if(firstVisibleItem >= zMIndex[22] + 1 && zMIndex[22] != 0) { topTitle.setText(letters[22]); }else if(firstVisibleItem >= zMIndex[21] + 1 && zMIndex[21] != 0) { topTitle.setText(letters[21]); }else if(firstVisibleItem >= zMIndex[20] + 1 && zMIndex[20] != 0) { topTitle.setText(letters[20]); }else if(firstVisibleItem >= zMIndex[19] + 1 && zMIndex[19] != 0) { topTitle.setText(letters[19]); }else if(firstVisibleItem >= zMIndex[18] + 1 && zMIndex[18] != 0) { topTitle.setText(letters[18]); }else if(firstVisibleItem >= zMIndex[17] + 1 && zMIndex[17] != 0) { topTitle.setText(letters[17]); }else if(firstVisibleItem >= zMIndex[16] + 1 && zMIndex[16] != 0) { topTitle.setText(letters[16]); }else if(firstVisibleItem >= zMIndex[15] + 1 && zMIndex[15] != 0) { topTitle.setText(letters[15]); }else if(firstVisibleItem >= zMIndex[14] + 1 && zMIndex[14] != 0) { topTitle.setText(letters[14]); }else if(firstVisibleItem >= zMIndex[13] + 1 && zMIndex[13] != 0) { topTitle.setText(letters[13]); }else if(firstVisibleItem >= zMIndex[12] + 1 && zMIndex[12] != 0) { topTitle.setText(letters[12]); }else if(firstVisibleItem >= zMIndex[11] + 1 && zMIndex[11] != 0) { topTitle.setText(letters[11]); }else if(firstVisibleItem >= zMIndex[10] + 1 && zMIndex[10] != 0) { topTitle.setText(letters[10]); }else if(firstVisibleItem >= zMIndex[9] + 1 && zMIndex[9] != 0) { topTitle.setText(letters[9]); }else if(firstVisibleItem >= zMIndex[8] + 1 && zMIndex[8] != 0) { topTitle.setText(letters[8]); }else if(firstVisibleItem >= zMIndex[7] + 1 && zMIndex[7] != 0) { topTitle.setText(letters[7]); }else if(firstVisibleItem >= zMIndex[6] + 1 && zMIndex[6] != 0) { topTitle.setText(letters[6]); }else if(firstVisibleItem >= zMIndex[5] + 1 && zMIndex[5] != 0) { topTitle.setText(letters[5]); }else if(firstVisibleItem >= zMIndex[4] + 1 && zMIndex[4] != 0) { topTitle.setText(letters[4]); }else if(firstVisibleItem >= zMIndex[3] + 1 && zMIndex[3] != 0) { topTitle.setText(letters[3]); }else if(firstVisibleItem >= zMIndex[2] + 1 && zMIndex[2] != 0) { topTitle.setText(letters[2]); }else if(firstVisibleItem >= zMIndex[1] + 1 && zMIndex[1] != 0) { topTitle.setText(letters[1]); }else if(firstVisibleItem >= zMIndex[0] + 1) { topTitle.setText(letters[0]); } } else { topTitle.setVisibility(View.GONE); } } };
城市实体类:
/** * Created by Luzj on 2018/8/23. * 城市列表item */public class CityInfo implements Serializable,Comparable { /** * 省市区标识 */ public int regionId; /** * 层级:0级为省、1级为市、2级为区 */ public int level; /** * 城市名称 */ public String name; /** * 拼音简称 */ public String pySname; /** * 编码 */ public String code; /** * 状态:0是无效,1是有效 */ public int status; /** * item类型:0为字母,1为城市带下黑线,2为城市不带下黑线 */ public int infoType; @Override public int compareTo(@NonNull CityInfo o) { CityInfo cityInfo = o; return this.pySname.compareTo(o.pySname); }}
附加Adapter(因城市列表数据给的是单独无序的一个列表,没有做字母排序,更没有用字母分字列表,所以拿到数据之后还要做按字母排序、分字母):
/** * Created by Luzj on 2018/8/23. */public class CityListAdapter extends BaseAdapter { private Context context; /** * 接口返回数据 */ private List datas; /** * 接口数据加上字母 */ private ArrayList allDatas = new ArrayList<>(); /** * item type,0为字母,1为带下黑线,2不带下黑线 */ private final int ZIMU = 0, ITEM_LINE = 1, ITEM_NOLINE = 2; /** * 字母所带列表 */ private ArrayList aL = new ArrayList<>(); private ArrayList bL = new ArrayList<>(); private ArrayList cL = new ArrayList<>(); private ArrayList dL = new ArrayList<>(); private ArrayList eL = new ArrayList<>(); private ArrayList fL = new ArrayList<>(); private ArrayList gL = new ArrayList<>(); private ArrayList hL = new ArrayList<>(); private ArrayList iL = new ArrayList<>(); private ArrayList jL = new ArrayList<>(); private ArrayList kL = new ArrayList<>(); private ArrayList lL = new ArrayList<>(); private ArrayList mL = new ArrayList<>(); private ArrayList nL = new ArrayList<>(); private ArrayList oL = new ArrayList<>(); private ArrayList pL = new ArrayList<>(); private ArrayList qL = new ArrayList<>(); private ArrayList rL = new ArrayList<>(); private ArrayList sL = new ArrayList<>(); private ArrayList tL = new ArrayList<>(); private ArrayList uL = new ArrayList<>(); private ArrayList vL = new ArrayList<>(); private ArrayList wL = new ArrayList<>(); private ArrayList xL = new ArrayList<>(); private ArrayList yL = new ArrayList<>(); private ArrayList zL = new ArrayList<>(); private static final String[] letters = {"A","B","C","D","E","F","G","H","I","J","K","L" ,"M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"}; /** * 总列表,每个元素都是一个字母列表 */ private ArrayList zMList = new ArrayList<>(); /** * 字母下标位置数组 */ private int[] zMIndexs = new int[26]; public CityListAdapter(Context context, List datas) { this.context = context; this.datas = datas; if(null != datas && datas.size() >= 0) { initDatas(); } } private void initDatas() { String firstChar; StringBuffer sb; //城市数据按照字母排序 Collections.sort(datas); //获取每个城市首字母进行归类 for(int i = 0; i < datas.size(); i++) { CityInfo c = datas.get(i); sb = new StringBuffer(c.pySname); firstChar = sb.delete(1, sb.length()).toString(); if("a".equals(firstChar)) { aL.add(c); }else if("b".equals(firstChar)) { bL.add(c); }else if("c".equals(firstChar)) { cL.add(c); }else if("d".equals(firstChar)) { dL.add(c); }else if("e".equals(firstChar)) { eL.add(c); }else if("f".equals(firstChar)) { fL.add(c); }else if("g".equals(firstChar)) { gL.add(c); }else if("h".equals(firstChar)) { hL.add(c); }else if("i".equals(firstChar)) { iL.add(c); }else if("j".equals(firstChar)) { jL.add(c); }else if("k".equals(firstChar)) { kL.add(c); }else if("l".equals(firstChar)) { lL.add(c); }else if("m".equals(firstChar)) { mL.add(c); }else if("n".equals(firstChar)) { nL.add(c); }else if("o".equals(firstChar)) { oL.add(c); }else if("p".equals(firstChar)) { pL.add(c); }else if("q".equals(firstChar)) { qL.add(c); }else if("r".equals(firstChar)) { rL.add(c); }else if("s".equals(firstChar)) { sL.add(c); }else if("t".equals(firstChar)) { tL.add(c); }else if("u".equals(firstChar)) { uL.add(c); }else if("v".equals(firstChar)) { vL.add(c); }else if("w".equals(firstChar)) { wL.add(c); }else if("x".equals(firstChar)) { xL.add(c); }else if("y".equals(firstChar)) { yL.add(c); }else if("z".equals(firstChar)) { zL.add(c); } } //依次将字母列表顺序添加进总列表 zMList.add(aL); zMList.add(bL); zMList.add(cL); zMList.add(dL); zMList.add(eL); zMList.add(fL); zMList.add(gL); zMList.add(hL); zMList.add(iL); zMList.add(jL); zMList.add(kL); zMList.add(lL); zMList.add(mL); zMList.add(nL); zMList.add(oL); zMList.add(pL); zMList.add(qL); zMList.add(rL); zMList.add(sL); zMList.add(tL); zMList.add(uL); zMList.add(vL); zMList.add(wL); zMList.add(xL); zMList.add(yL); zMList.add(zL); CityInfo cZiMu; CityInfo c; for(int i = 0; i < letters.length; i++) { if(zMList.get(i).size() > 0) { //每开始取一个字母列表,先添加进该字母 cZiMu = new CityInfo(); cZiMu.infoType = 0; cZiMu.name = letters[i]; allDatas.add(cZiMu); zMIndexs[i] = allDatas.indexOf(cZiMu); for(int j = 0; j < zMList.get(i).size(); j++) { c = (CityInfo) zMList.get(i).get(j); if(j == (zMList.get(i).size() - 1)) { //当该城市是该字母列表最后一个时,取消下黑线 c.infoType = 2; }else { c.infoType = 1; } allDatas.add(c); } } } } /** * @return 字母下标数组 */ public int[] getzMIndexs() { return zMIndexs; } @Override public View getView(int position, View convertView, ViewGroup parent) { int type = allDatas.get(position).infoType; if(ZIMU == type) { convertView = getZiMuView(position, convertView, parent); }else { convertView = getItemLineView(position, convertView, parent); } return convertView; } public void updateData(List datas) { this.datas = datas; notifyDataSetChanged(); } private Map letterIndex = new HashMap<>(); private View getZiMuView(int position, View convertView, ViewGroup parent) { ZiMuHolder zM; if(null == convertView) { convertView = LayoutInflater.from(context).inflate(R.layout.citylist_item0, null); zM = new ZiMuHolder(convertView); convertView.setTag(zM); }else { zM = (ZiMuHolder) convertView.getTag(); } zM.citylistZm.setText(allDatas.get(position).name); return convertView; } private View getItemLineView(int position, View convertView, ViewGroup parent) { CityListItem1 c1; if(null == convertView) { convertView = LayoutInflater.from(context).inflate(R.layout.citylist_item1, parent, false); c1 = new CityListItem1(convertView); convertView.setTag(c1); }else { c1 = (CityListItem1) convertView.getTag(); } c1.citylistItem1.setText(allDatas.get(position).name); c1.citylistItem1.setTag(allDatas.get(position)); if(ITEM_LINE == allDatas.get(position).infoType) { c1.line.setVisibility(View.VISIBLE); } return convertView; } @Override public int getItemViewType(int position) { CityInfo cityInfo = allDatas.get(position); int type = cityInfo.infoType; if(ZIMU == type) { return ZIMU; }else if(ITEM_LINE == type) { return ITEM_LINE; }else { return ITEM_NOLINE; } } @Override public int getViewTypeCount() { return 3; } @Override public int getCount() { return null == allDatas ? 0 : allDatas.size(); } @Override public Object getItem(int position) { if(null == allDatas) { return null; }else { return allDatas.get(position); } } @Override public long getItemId(int position) { return position; } public List getAllDatas() { return allDatas;} class ZiMuHolder { TextView citylistZm; ZiMuHolder(View v) { citylistZm = (TextView) v.findViewById(R.id.citylist_zm); } } class CityListItem1 { TextView citylistItem1; View line; CityListItem1(View v) { citylistItem1 = (TextView) v.findViewById(R.id.citylist_item1); citylistItem1.setOnClickListener(onClickListener); line = v.findViewById(R.id.bottom_line); line.setVisibility(View.GONE); } } private View.OnClickListener onClickListener = new View.OnClickListener() { @Override public void onClick(View v) { onCityListClickListener.onCityListClickListener(v); } }; private OnCityListItemClickListener onCityListClickListener; public interface OnCityListItemClickListener { void onCityListClickListener(View v); } public void setOnCityListClickListener(OnCityListItemClickListener listener) { this.onCityListClickListener = listener; }}
后台数据接口:
{ "code":"mock", //类型:String 必有字段 备注:响应状态码 0成功、!=0 不成功 "message":"mock", //类型:String 必有字段 备注:响应提示消息 "data": - { //类型:Object 必有字段 备注:无 "cityList": - [ //类型:Array 必有字段 备注:城市列表 - { //类型:Object 必有字段 备注:无 "regionId":1, //类型:Number 必有字段 备注:省市区标识 "level":1, //类型:Number 必有字段 备注:层级:0级为省、1级为市、2级为区 "name":"mock", //类型:String 必有字段 备注:城市名称 "pySname":"mock", //类型:String 必有字段 备注:拼音简称 "code":"mock", //类型:String 必有字段 备注:编码 "status":1 //类型:Number 必有字段 备注:状态:0是无效,1是有效 } ] }}
更多相关文章
- Spinner 下拉列表 demo
- 图像列表(Gallery、ImageSwithcer)
- Android -联系人列表
- android 获取正在运行的应用程序列表
- Android 获取默认输入法,以及获取输入法的列表的方法
- Android使用RecyclerView实现瀑布流效果的列表展示
- Android中如何使用列表对话框
- android edittext只能输入字母和数字,默认弹出英文输入法
- android sqlite3 数据库升级,加字段