【Android】城市列表,字母吸顶

效果动图:

(后面补上)

总体布局:




    
    

    
    

    
    

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是有效
            }
        ]
    }
}

 

你可能感兴趣的:(Android)