效果動圖:
(後面補上)
總體佈局:
<?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"
style="@style/CommonBg_Gray">
<!--吸頂標題-->
<TextView
android:id="@+id/item_title_top"
android:layout_width="match_parent"
android:layout_height="@dimen/x80"
android:background="@color/more_light_gray"
android:gravity="left|center_vertical"
android:paddingLeft="@dimen/x30"
style="@style/Txt_3_R_26"
android:clickable="true"
android:visibility="gone"/>
<!--城市列表-->
<ListView
android:id="@+id/list_citylist"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="@style/CommonListNoLine"
/>
<!--字母導航-->
<com.uhome.base.common.view.MyLetterListView
android:id="@+id/letterlist"
android:layout_width="@dimen/x50"
android:layout_height="@dimen/x800"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
/>
</RelativeLayout>
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);
}
}
};
附加Adapter(因城市列表數據給的是單獨無序的一個列表,沒有做字母排序,更沒有用字母分字列表,所以拿到數據之後還要做按字母排序、分字母):
/**
* Created by Luzj on 2018/8/23.
*/
public class CityListAdapter extends BaseAdapter {
private Context context;
/**
* 接口返回數據
*/
private List<CityInfo> datas;
/**
* 接口數據加上字母
*/
private ArrayList<CityInfo> allDatas = new ArrayList<>();
/**
* item type,0爲字母,1爲帶下黑線,2不帶下黑線
*/
private final int ZIMU = 0, ITEM_LINE = 1, ITEM_NOLINE = 2;
/**
* 字母所帶列表
*/
private ArrayList<CityInfo> aL = new ArrayList<>();
private ArrayList<CityInfo> bL = new ArrayList<>();
private ArrayList<CityInfo> cL = new ArrayList<>();
private ArrayList<CityInfo> dL = new ArrayList<>();
private ArrayList<CityInfo> eL = new ArrayList<>();
private ArrayList<CityInfo> fL = new ArrayList<>();
private ArrayList<CityInfo> gL = new ArrayList<>();
private ArrayList<CityInfo> hL = new ArrayList<>();
private ArrayList<CityInfo> iL = new ArrayList<>();
private ArrayList<CityInfo> jL = new ArrayList<>();
private ArrayList<CityInfo> kL = new ArrayList<>();
private ArrayList<CityInfo> lL = new ArrayList<>();
private ArrayList<CityInfo> mL = new ArrayList<>();
private ArrayList<CityInfo> nL = new ArrayList<>();
private ArrayList<CityInfo> oL = new ArrayList<>();
private ArrayList<CityInfo> pL = new ArrayList<>();
private ArrayList<CityInfo> qL = new ArrayList<>();
private ArrayList<CityInfo> rL = new ArrayList<>();
private ArrayList<CityInfo> sL = new ArrayList<>();
private ArrayList<CityInfo> tL = new ArrayList<>();
private ArrayList<CityInfo> uL = new ArrayList<>();
private ArrayList<CityInfo> vL = new ArrayList<>();
private ArrayList<CityInfo> wL = new ArrayList<>();
private ArrayList<CityInfo> xL = new ArrayList<>();
private ArrayList<CityInfo> yL = new ArrayList<>();
private ArrayList<CityInfo> 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<List> 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<String, Integer> 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是有效
}
]
}
}