热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android开发实现选择城市界面,可根据拼音、首字母进行搜索

短短的国庆8天假期一眨眼就过去了,下次长假只有等到过年了,本宝宝不开心。既然已经开始工作了,就要好好多学习点新知识,来提高自

短短的国庆8天假期一眨眼就过去了,下次长假只有等到过年了,本宝宝不开心。既然已经开始工作了,就要好好多学习点新知识,来提高自己的代码能力,今天带大家去实现简易的选择城市界面,并且可以根据城市首字母或者拼音搜索。先来看下我的效果图:

 

在写代码之前先准备好一个城市列表的json文件以及去百度或者高德申请定位功能,Demo在文章最后。(Demo里没有写定位功能,需要自己实现哦~)

实现方法也比较简单,我就简单的给大家说一下,整个城市列表是用的一个ListView,方便我们后面监听它的滚动状态,右边的快速定位栏是自定义View,代码比较简单,我就直接放代码了。不知道大家发现没有,有些字母开头的城市是没有的,比如 I,O,U,V等等,为了节约空间我就把那几个字母去掉了,有的软件是把26个字母全部保留了。

(其实都不影响,看你个人吧,我反正是有强迫症的。)注意,在自定义View的时候三种构造方法都要写上,千万不要偷懒!!!哎,都是泪  o(╥﹏╥)o

 

public class LetterListView extends View {OnTouchingLetterChangedListener onTouchingLetterChangedListener;public static String[] b = {"定位", "热门", "A", "B", "C", "D", "E", "F", "G", "H", "J", "K","L", "M", "N", "P", "Q", "R", "S", "T", "W", "X", "Y", "Z"};int choose = -1;Paint paint = new Paint();boolean showBkg = false;private Context mContext;public LetterListView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init(context);}public LetterListView(Context context, AttributeSet attrs) {super(context, attrs);init(context);}public LetterListView(Context context) {super(context);init(context);}private void init(Context context){this.mContext = context;paint.setColor(Color.parseColor("#50B3DA"));paint.setTextSize(DisplayUtil.sp2px(mContext, 12));paint.setAntiAlias(true);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (showBkg) {canvas.drawColor(Color.parseColor("#40000000"));}int height = getHeight();int width = getWidth();int singleHeight = height / b.length;for (int i = 0; i = 0 && c = 0 && c


使用的时候设置好宽度和高度:

 

 


 

 

接下来就是关键的地方了,咳咳~

 

一、 既然左边用到了ListView,那就少不了适配器和城市模型。

①、城市模型:其中拼音和首字母是方便用户搜索的时候进行筛选,CityCode你们可以不用去管,我主要是用来请求数据。

 

public class CityEntity {private String name;private String key;private String pinyin; //全拼private String first; //首字母private String cityCode;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getKey() {return key;}public void setKey(String key) {this.key = key;}public String getPinyin() {return pinyin;}public void setPinyin(String pinyin) {this.pinyin = pinyin;}public String getFirst() {return first;}public void setFirst(String first) {this.first = first;}public String getCityCode() {return cityCode;}public void setCityCode(String cityCode) {this.cityCode = cityCode;}
}


②、全部城市列表的适配器:我这里将全部城市列表分成了三种类型,第一种就是当前定位城市的布局,第二种就是热门城市的布局,(当然了,热门城市你们可以从后台获取,我图方便就写死在本地了),第三种就是全部城市的布局了

 

 

/*** 总城市适配器*/private class CityListAdapter extends BaseAdapter {private Context context;private List totalCityList;private List hotCityList;private LayoutInflater inflater;final int VIEW_TYPE &#61; 3;CityListAdapter(Context context,List totalCityList,List hotCityList) {this.context &#61; context;this.totalCityList &#61; totalCityList;this.hotCityList &#61; hotCityList;inflater &#61; LayoutInflater.from(context);alphaIndexer &#61; new HashMap<>();for (int i &#61; 0; i &#61; 0 ? totalCityList.get(i - 1).getKey() : " ";if (!previewStr.equals(currentStr)) {String name &#61; getAlpha(currentStr);alphaIndexer.put(name, i);}}}&#64;Overridepublic int getViewTypeCount() {return VIEW_TYPE;}&#64;Overridepublic int getItemViewType(int position) {return position <2 ? position : 2;}&#64;Overridepublic int getCount() {return totalCityList &#61;&#61; null ? 0 : totalCityList.size();}&#64;Overridepublic Object getItem(int position) {return totalCityList.get(position);}&#64;Overridepublic long getItemId(int position) {return position;}&#64;Overridepublic View getView(int position, View convertView, ViewGroup parent) {final TextView curCityNameTv;ViewHolder holder;int viewType &#61; getItemViewType(position);if (viewType &#61;&#61; 0) { // 定位convertView &#61; inflater.inflate(R.layout.select_city_location_item, null);LinearLayout noLocationLl &#61; (LinearLayout) convertView.findViewById(R.id.cur_city_no_data_ll);TextView getLocationTv &#61; (TextView) convertView.findViewById(R.id.cur_city_re_get_location_tv);curCityNameTv &#61; (TextView) convertView.findViewById(R.id.cur_city_name_tv);if (TextUtils.isEmpty(locationCity)) {noLocationLl.setVisibility(View.VISIBLE);curCityNameTv.setVisibility(View.GONE);getLocationTv.setOnClickListener(new View.OnClickListener() {&#64;Overridepublic void onClick(View v) {initLocation();}});} else {noLocationLl.setVisibility(View.GONE);curCityNameTv.setVisibility(View.VISIBLE);curCityNameTv.setText(locationCity);curCityNameTv.setOnClickListener(new View.OnClickListener() {&#64;Overridepublic void onClick(View v) {if (!locationCity.equals(UserConstant.curSelCity)) {//设置城市代码String cityCode &#61; "";for (CityEntity cityEntity : AppCache.getInstance().getCurCityList()) {if (cityEntity.getName().equals(locationCity)) {cityCode &#61; cityEntity.getCityCode();break;}}showSetCityDialog(locationCity, cityCode);} else {ToastUtils.show("当前定位城市" &#43; curCityNameTv.getText().toString());}}});}} else if (viewType &#61;&#61; 1) { //热门城市convertView &#61; inflater.inflate(R.layout.recent_city_item, null);GridView hotCityGv &#61; (GridView) convertView.findViewById(R.id.recent_city_gv);hotCityGv.setAdapter(new HotCityListAdapter(context, this.hotCityList));hotCityGv.setOnItemClickListener(new AdapterView.OnItemClickListener() {&#64;Overridepublic void onItemClick(AdapterView parent, View view,int position, long id) {CityEntity cityEntity &#61; hotCityList.get(position);showSetCityDialog(cityEntity.getName(), cityEntity.getCityCode());}});} else {if (null &#61;&#61; convertView) {holder &#61; new ViewHolder();convertView &#61; inflater.inflate(R.layout.city_list_item_layout, null);ViewBinder.bind(holder, convertView);convertView.setTag(holder);} else {holder &#61; (ViewHolder) convertView.getTag();}CityEntity cityEntity &#61; totalCityList.get(position);holder.cityKeyTv.setVisibility(View.VISIBLE);holder.cityKeyTv.setText(getAlpha(cityEntity.getKey()));holder.cityNameTv.setText(cityEntity.getName());if (position >&#61; 1) {CityEntity preCity &#61; totalCityList.get(position - 1);if (preCity.getKey().equals(cityEntity.getKey())) {holder.cityKeyTv.setVisibility(View.GONE);} else {holder.cityKeyTv.setVisibility(View.VISIBLE);}}}return convertView;}private class ViewHolder {&#64;Bind(R.id.city_name_tv)TextView cityNameTv;&#64;Bind(R.id.city_key_tv)TextView cityKeyTv;}}

1&#xff09;、当前定位城市布局&#xff1a;定位失败的话显示出来&#xff0c;并且提示用户去开启GPS

 

 


2&#xff09;、热门城市布局&#xff1a;记住&#xff0c;这里直接使用GridView的话只会显示一行数据&#xff0c;需要继承GridView并重写OnMeasure方法&#xff0c;网上有很多案例&#xff0c;就不放代码了。

 

 


3&#xff09;、全部城市的单行布局&#xff1a;每绘制一条数据判断前一个数据的Key是否与现在的相同&#xff0c;true则不显示  city_key_tv&#xff0c;保证同一个Key的城市只有一个显示。

 

 


③、热门城市列表适配器&#xff1a;比较简单&#xff0c;不过多说明。

 

 

/*** 热门城市适配器*/private class HotCityListAdapter extends BaseAdapter {private List cityEntities;private LayoutInflater inflater;HotCityListAdapter(Context mContext, List cityEntities) {this.cityEntities &#61; cityEntities;inflater &#61; LayoutInflater.from(mContext);}&#64;Overridepublic int getCount() {return cityEntities &#61;&#61; null ? 0 : cityEntities.size();}&#64;Overridepublic Object getItem(int position) {return cityEntities.get(position);}&#64;Overridepublic long getItemId(int position) {return position;}&#64;Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder;if (null &#61;&#61; convertView) {holder &#61; new ViewHolder();convertView &#61; inflater.inflate(R.layout.city_list_grid_item_layout, null);ViewBinder.bind(holder, convertView);convertView.setTag(holder);} else {holder &#61; (ViewHolder) convertView.getTag();}CityEntity cityEntity &#61; cityEntities.get(position);holder.cityNameTv.setText(cityEntity.getName());return convertView;}private class ViewHolder {&#64;Bind(R.id.city_list_grid_item_name_tv)TextView cityNameTv;}}


二、初始化首字母提示框&#xff0c;并且设置ListVIew的滚动监听以及自定义View的Touch事件

 

 

/*** 初始化汉语拼音首字母弹出提示框*/private void initOverlay() {mReady &#61; true;LayoutInflater inflater &#61; LayoutInflater.from(this);overlay &#61; (TextView) inflater.inflate(R.layout.overlay, null);overlay.setVisibility(View.INVISIBLE);WindowManager.LayoutParams lp &#61; new WindowManager.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.TYPE_APPLICATION,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,PixelFormat.TRANSLUCENT);WindowManager windowManager &#61; (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);windowManager.addView(overlay, lp);}

 

private class LetterListViewListener implementsLetterListView.OnTouchingLetterChangedListener {&#64;Overridepublic void onTouchingLetterChanged(final String s) {isScroll &#61; false;if (alphaIndexer.get(s) !&#61; null) {int position &#61; alphaIndexer.get(s);totalCityLv.setSelection(position);overlay.setText(s);overlay.setVisibility(View.VISIBLE);handler.removeCallbacks(overlayThread);// 延迟让overlay为不可见handler.postDelayed(overlayThread, 700);}}}/*** 设置overlay不可见*/private class OverlayThread implements Runnable {&#64;Overridepublic void run() {overlay.setVisibility(View.GONE);}}&#64;Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {if (scrollState &#61;&#61; SCROLL_STATE_TOUCH_SCROLL|| scrollState &#61;&#61; SCROLL_STATE_FLING) {isScroll &#61; true;} else {isScroll &#61; false;}}&#64;Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {if (!isScroll) {return;}if (mReady) {String key &#61; getAlpha(totalCityList.get(firstVisibleItem).getKey());overlay.setText(key);overlay.setVisibility(View.VISIBLE);handler.removeCallbacks(overlayThread);// 延迟让overlay为不可见handler.postDelayed(overlayThread, 700);}}


其中最主要关键的地方就是以上这些了

最后我就放上demo的下载地址了&#xff0c;Demo点我

就是这些了&#xff0c;祝大家第一天工作愉快~

-------------------------------

2019-10-09更新

CSDN当初上传设置的最低1分&#xff0c;现在居然涨到50了&#xff0c;&#xff0c;&#xff0c;过分。现在传到了百度云&#xff0c;  提取码&#xff1a;l7ip

欢迎自取&#xff0c;好用的话&#xff0c;不放点个关注。谢谢~~


推荐阅读
author-avatar
啊沙发的非飞
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有