在做一些APP的时候可能会用到城市选择模块的功能,本实例可以提供位置自定定位和手动选择的功能,非常好用,大家可以修改后加入自己的项目中。

首先看一下效果:

1.进入有的手机可能会提示权限要求,这时我们选择允许。

2.选择允许后进入:

这个位置可以看到我们的城市已经通过GPS获取到了

点击这个控件,城市获取完成了:

下面我们看一下关键代码如何实现这个功能效果。

1.MainActivity.java:

package com.winxiang.locationselect;import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;public class MainActivity extends Activity {private TextView city_name;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);city_name = (TextView) findViewById(R.id.city_name);}public void goSelcet(View v){startActivityForResult(new Intent(MainActivity.this,ActivitySelectCity.class), 99);}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {// TODO Auto-generated method stubtry{switch (resultCode) {case 99:city_name.setText(data.getStringExtra("lngCityName"));break;default:break;}}catch (Exception e) {e.printStackTrace();}super.onActivityResult(requestCode, resultCode, data);}
}

很是简单,有一个跳转按钮。

2.ActivitySelectCity.java:

package com.winxiang.locationselect;import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Pattern;import org.json.JSONArray;
import org.json.JSONObject;import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;import com.winxiang.locationselect.MyLetterListView.OnTouchingLetterChangedListener;public class ActivitySelectCity extends Activity{private ListAdapter adapter;private ListView personList;private ImageView imgback;private TextView overlay; // 对话框首字母textviewprivate MyLetterListView letterListView; // A-Z listviewprivate HashMap<String, Integer> alphaIndexer;// 存放存在的汉语拼音首字母和与之对应的列表位置private String[] sections;// 存放存在的汉语拼音首字母private Handler handler;private OverlayThread overlayThread; // 显示首字母对话框private ArrayList<City> allCity_lists; // 所有城市列表private ArrayList<City> ShowCity_lists; // 需要显示的城市列表-随搜索而改变private ArrayList<City> city_lists;// 城市列表private String lngCityName ="";//存放返回的城市名private JSONArray chineseCities ;private LocationClient locationClient = null;private EditText sh;private TextView lng_city;private LinearLayout lng_city_lay;private ProgressDialog progress;private static final int SHOWDIALOG = 2;private static final int DISMISSDIALOG = 3;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_selectcity);personList = (ListView) findViewById(R.id.list_view);allCity_lists = new ArrayList<City>();letterListView = (MyLetterListView) findViewById(R.id.MyLetterListView01);lng_city_lay = (LinearLayout) findViewById(R.id.lng_city_lay);sh = (EditText) findViewById(R.id.sh);lng_city = (TextView) findViewById(R.id.lng_city);imgback = (ImageView) findViewById(R.id.imgback);letterListView.setOnTouchingLetterChangedListener(new LetterListViewListener());alphaIndexer = new HashMap<String, Integer>();handler = new Handler();overlayThread = new OverlayThread();personList.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {Intent intent = new Intent();intent.putExtra("lngCityName", ShowCity_lists.get(arg2).name);setResult(99,intent);finish();}});lng_city_lay.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent();intent.putExtra("lngCityName",lngCityName);setResult(99,intent);finish();}});imgback.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {finish();}});initGps();initOverlay();handler2.sendEmptyMessage(SHOWDIALOG);Thread thread = new Thread(){@Overridepublic void run() {hotCityInit();handler2.sendEmptyMessage(DISMISSDIALOG);super.run();}};thread.start();}/*** 热门城市*/public void hotCityInit() {City city;   city = new City("上海", "");allCity_lists.add(city);city = new City("北京", "");allCity_lists.add(city);city = new City("广州", "");allCity_lists.add(city);city = new City("深圳", "");allCity_lists.add(city);city = new City("武汉", "");allCity_lists.add(city);city = new City("天津", "");allCity_lists.add(city);city = new City("西安", "");allCity_lists.add(city);city = new City("南京", "");allCity_lists.add(city);city = new City("杭州", "");allCity_lists.add(city);city = new City("成都", "");allCity_lists.add(city);city = new City("重庆", "");allCity_lists.add(city);city_lists = getCityList();allCity_lists.addAll(city_lists);ShowCity_lists=allCity_lists;}/*** * 通过json数据获取城市列表* @author yayun* @since 2015年9月18日*@return*/private ArrayList<City> getCityList() {ArrayList<City> list = new ArrayList<City>();try {chineseCities = new JSONArray(getResources().getString(R.string.citys));for(int i=0;i<chineseCities.length();i++){JSONObject jsonObject = chineseCities.getJSONObject(i);City city = new City(jsonObject.getString("name"), jsonObject.getString("pinyin"));list.add(city);}} catch (Exception e) {e.printStackTrace();}Collections.sort(list, comparator);return list;}/*** a-z排序*/Comparator comparator = new Comparator<City>() {@Overridepublic int compare(City lhs, City rhs) {String a = lhs.getPinyi().substring(0, 1);String b = rhs.getPinyi().substring(0, 1);int flag = a.compareTo(b);if (flag == 0) {return a.compareTo(b);} else {return flag;}}};/*** ListView的adapter* @author yayun* @since 2015年9月18日**/public class ListAdapter extends BaseAdapter {private LayoutInflater inflater;final int VIEW_TYPE = 3;public ListAdapter(Context context) {this.inflater = LayoutInflater.from(context);alphaIndexer = new HashMap<String, Integer>();sections = new String[ShowCity_lists.size()];for (int i = 0; i < ShowCity_lists.size(); i++) {// 当前汉语拼音首字母String currentStr = getAlpha(ShowCity_lists.get(i).getPinyi());// 上一个汉语拼音首字母,如果不存在为“ ”String previewStr = (i - 1) >= 0 ? getAlpha(ShowCity_lists.get(i - 1).getPinyi()) : " ";if (!previewStr.equals(currentStr)) {String name = getAlpha(ShowCity_lists.get(i).getPinyi());alphaIndexer.put(name, i);sections[i] = name;}}}@Overridepublic int getCount() {return ShowCity_lists.size();}@Overridepublic Object getItem(int position) {return ShowCity_lists.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic int getItemViewType(int position) {// TODO Auto-generated method stubint type = 2;if (position == 0&&sh.getText().length()==0) {//不是在搜索状态下type = 0;}return type;}@Overridepublic int getViewTypeCount() {// 这里需要返回需要集中布局类型,总大小为类型的种数的下标return VIEW_TYPE;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder;int viewType = getItemViewType(position);if (convertView == null) {convertView = inflater.inflate(R.layout.list_item, null);holder = new ViewHolder();holder.alpha = (TextView) convertView.findViewById(R.id.alpha);holder.name = (TextView) convertView.findViewById(R.id.name);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}
//              if (sh.getText().length()==0) {//搜所状态
//                  holder.name.setText(list.get(position).getName());
//                  holder.alpha.setVisibility(View.GONE);
//              }else if(position>0){//显示拼音和热门城市,一次检查本次拼音和上一个字的拼音,如果一样则不显示,如果不一样则显示holder.name.setText(ShowCity_lists.get(position).getName());String currentStr = getAlpha(ShowCity_lists.get(position).getPinyi());//本次拼音String previewStr = (position-1) >= 0 ? getAlpha(ShowCity_lists.get(position-1).getPinyi()) : " ";//上一个拼音if (!previewStr.equals(currentStr)) {//不一样则显示holder.alpha.setVisibility(View.VISIBLE);if (currentStr.equals("#")) {currentStr = "热门城市";}holder.alpha.setText(currentStr);} else {holder.alpha.setVisibility(View.GONE);}
//              }return convertView;}private class ViewHolder {TextView alpha; // 首字母标题TextView name; // 城市名字}}// 初始化汉语拼音首字母弹出提示框private void initOverlay() {LayoutInflater inflater = LayoutInflater.from(this);overlay = (TextView) inflater.inflate(R.layout.overlay, null);overlay.setVisibility(View.INVISIBLE);WindowManager.LayoutParams lp = new WindowManager.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.TYPE_APPLICATION,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,PixelFormat.TRANSLUCENT);WindowManager windowManager = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);windowManager.addView(overlay, lp);}private class LetterListViewListener implementsOnTouchingLetterChangedListener {@Overridepublic void onTouchingLetterChanged(final String s) {if (alphaIndexer.get(s) != null) {int position = alphaIndexer.get(s);personList.setSelection(position);overlay.setText(sections[position]);overlay.setVisibility(View.VISIBLE);handler.removeCallbacks(overlayThread);// 延迟一秒后执行,让overlay为不可见handler.postDelayed(overlayThread, 1500);}}}// 设置overlay不可见private class OverlayThread implements Runnable {@Overridepublic void run() {overlay.setVisibility(View.GONE);}}// 获得汉语拼音首字母private String getAlpha(String str) {if (str.equals("-")) {return "&";}if (str == null) {return "#";}if (str.trim().length() == 0) {return "#";}char c = str.trim().substring(0, 1).charAt(0);// 正则表达式,判断首字母是否是英文字母Pattern pattern = Pattern.compile("^[A-Za-z]+$");if (pattern.matcher(c + "").matches()) {return (c + "").toUpperCase();} else {return "#";}}/*** * 初始化GPS* @author yayun* @since 2015年9月18日*/private void initGps() {try{MyLocationListenner myListener = new MyLocationListenner();locationClient = new LocationClient(ActivitySelectCity.this); locationClient.registerLocationListener(myListener);LocationClientOption option = new LocationClientOption();option.setOpenGps(true);option.setAddrType("all");option.setCoorType("bd09ll");option.setScanSpan(5000);option.disableCache(true);option.setPoiNumber(5); option.setPoiDistance(1000); option.setPoiExtraInfo(true); option.setPriority(LocationClientOption.GpsFirst);locationClient.setLocOption(option);locationClient.start();}catch (Exception e) {e.printStackTrace();}}/*** 销毁*/@Overridepublic void onDestroy() {super.onDestroy();locationClient.stop();}/*** 通过位置SDK获取现在所在城市* @author yayun* @since 2015年9月18日**/private class MyLocationListenner implements BDLocationListener {@Overridepublic void onReceiveLocation(BDLocation location) {if (location == null)return;StringBuffer sb = new StringBuffer(256);if (location.getLocType() == BDLocation.TypeGpsLocation) {sb.append(location.getCity());} else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {sb.append(location.getCity());}if (sb.toString() != null && sb.toString().length() > 0) {lngCityName=sb.toString();lng_city.setText(lngCityName);}}public void onReceivePoi(BDLocation poiLocation) {}}Handler handler2 = new Handler(){public void handleMessage(android.os.Message msg) {switch (msg.what) {case SHOWDIALOG:progress = AppUtil.showProgress(ActivitySelectCity.this, "正在加载数据,请稍候...");break;case DISMISSDIALOG:if (progress != null){progress.dismiss();}adapter = new ListAdapter(ActivitySelectCity.this);personList.setAdapter(adapter);
//              personList.setAdapter(adapter);sh.addTextChangedListener(new TextWatcher() {@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {}@Overridepublic void beforeTextChanged(CharSequence s, int start, int count,int after) {}@Overridepublic void afterTextChanged(Editable s) {//搜索符合用户输入的城市名if(s.length()>0){ArrayList<City> changecity = new ArrayList<City>();for(int i=0;i<city_lists.size();i++){if(city_lists.get(i).name.indexOf(sh.getText().toString())!=-1){changecity.add(city_lists.get(i));}}ShowCity_lists = changecity;}else{ShowCity_lists = allCity_lists;}adapter.notifyDataSetChanged();}});break;default:break;}};};
}

3.自定义控件(快速索引):

package com.winxiang.locationselect;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.text.style.TypefaceSpan;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;public class MyLetterListView extends View {OnTouchingLetterChangedListener onTouchingLetterChangedListener;String[] b = { "#", "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" };int choose = -1;Paint paint = new Paint();boolean showBkg = false;public MyLetterListView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}public MyLetterListView(Context context, AttributeSet attrs) {super(context, attrs);}public MyLetterListView(Context context) {super(context);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (showBkg) {canvas.drawColor(Color.parseColor("#10000000"));}int height = getHeight();int width = getWidth();int singleHeight = height / b.length;for (int i = 0; i < b.length; i++) {paint.setColor(Color.parseColor("#515151"));paint.setTypeface(Typeface.DEFAULT_BOLD);paint.setAntiAlias(true);if (i == choose) {paint.setColor(Color.parseColor("#3399ff"));paint.setFakeBoldText(true);}float xPos = width / 2 - paint.measureText(b[i]) / 2;float yPos = singleHeight * i + singleHeight;canvas.drawText(b[i], xPos, yPos, paint);paint.reset();}}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {final int action = event.getAction();final float y = event.getY();final int oldChoose = choose;final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;final int c = (int) (y / getHeight() * b.length);switch (action) {case MotionEvent.ACTION_DOWN:showBkg = true;if (oldChoose != c && listener != null) {if (c >= 0 && c <= b.length) {listener.onTouchingLetterChanged(b[c]);choose = c;invalidate();}}break;case MotionEvent.ACTION_MOVE:if (oldChoose != c && listener != null) {if (c >= 0 && c <= b.length) {listener.onTouchingLetterChanged(b[c]);choose = c;invalidate();}}break;case MotionEvent.ACTION_UP:showBkg = false;choose = -1;invalidate();break;}return true;}@Overridepublic boolean onTouchEvent(MotionEvent event) {return super.onTouchEvent(event);}public void setOnTouchingLetterChangedListener(OnTouchingLetterChangedListener onTouchingLetterChangedListener) {this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;}public interface OnTouchingLetterChangedListener {public void onTouchingLetterChanged(String s);}}

运行一下效果:


介于篇幅问题,其他代码大家可以下载源码查看:

源码下载

喜欢的朋友关注一下我和我的公众号,谢谢!

Android实战简易教程-第六十枪(分享一个城市选择功能模块)相关推荐

  1. Android实战简易教程-第六十六枪(服务器端搭建和服务器端Json数据交互)

    学习Android有一段时间了,对服务器端有很深的好奇,决定对服务器端的实现进行一些研究,这里实现了一个简单的小例子,用于获取服务器端的json数据,例子很简单,适合初学者学习使用. 服务器端 首先我 ...

  2. Android实战简易教程-第六十五枪(自定义控件实现数字液晶时钟Demo)

    下面我们研究一下如何实现一个数字液晶时钟,本质属于特效一种哈. 首先创建一个布局文件: <?xml version="1.0" encoding="utf-8&qu ...

  3. Android实战简易教程-第五十枪(工具类的测试)

    在开发中,为了提高开发效率,我们一般会自定义自己的工具类.为了保证项目的可靠性,在将工具类引入项目之前,我们一般都会对工具类进行单元测试,下面我们通过一个实例看一下如何搭建测试环境. 1.首先自定义一 ...

  4. Android实战简易教程-第三十九枪(第三方短信验证平台Mob和验证码自动填入功能结合实例)

    用户注册或者找回密码时一般会用到短信验证功能,这里我们使用第三方的短信平台进行验证实例. 我们用到第三方短信验证平台是Mob,地址为:http://mob.com/ 一.注册用户.获取SDK 大家可以 ...

  5. Android实战简易教程-第五十一枪(ListView实现子控件的动态显示和隐藏、checkbox全选和反选)

    前段时间写过一篇文章:Android实战简易教程-第四十七枪(ListView多选-实现点餐系统)有的同学留言建议,可不可以动态控制checkbox的显示和全选反选功能,我研究了一下,发现实现也比较容 ...

  6. Android实战简易教程-第三十六枪(监听短信-实现短信验证码自动填入)

    一般用户喜欢用手机号作为用户名注册APP账号,这时一般都是通过手机验证码的方式进行验证,下面我们就研究一个非常实用的方法,通过监听短信-实现短信验证码的自动填入,提高用户体验. 首先我们看一下如何监听 ...

  7. Android实战简易教程-第七十五枪(WIFI直连工具类)

    设置指定的WIFI用户名密码和加密方式,可以进行WIFI直连. 1.工具类-WifiUtil.java: package demo.androidwar.com.myapplication;impor ...

  8. Android实战简易教程-第三十四枪(基于ViewPager和FragmentPagerAdapter实现滑动通用Tab)...

    上一段时间写过一篇文章<基于ViewPager实现微信页面切换效果> 里面实现了相似微信Tab的页面.可是这样的实现方法有个问题.就是以后全部的代码逻辑都必须在MainActivity中实 ...

  9. Android实战简易教程-第五十七枪(分享小米手电筒源码)

    手电筒功能实现简单很实用,下面我们就来研究一下如何自制一款手电筒小程序,初学者可以通过实例了解原理,提高学习android技术的热情和动力. 首先我们了解一下手电筒要调用哪些android权限: &l ...

最新文章

  1. 宁波大学计算机王老师,王翀_宁波大学研究生导师信息
  2. 打开闪光灯java代码_android 拍照带水印(可打开闪光灯功能)
  3. 中空字符串有什么用_中空玻璃中还要充氩气、还要防泄漏、你知道吗?
  4. 8 list切片_Python中14个切片操作,你常用哪几个?
  5. centos build-essential 报错
  6. [计组]寄存器和存储器的区别
  7. matlab中欠定方程组超定方程组_《数值天气预报》:球坐标系中的基本方程组
  8. 融资租赁业务的基本知识
  9. ELK之收集haproxy日志
  10. python之yield
  11. python爬虫怎么挣钱_2019如何学Python?这里有你需要的答案
  12. c语言中什么函数可以作为虚函数,C++语言中的“虚函数”就像C语言中的指针,必须要弄懂的...
  13. Silverlight 2中多语言支持实现(下)
  14. php7 libiconv,CentOS 7下编译libiconv
  15. 2022-05-24 游程编码与位图压缩(C++)
  16. C语言程序设计题(带答案)
  17. JavaScript中this的使用(四种情况下this的指向)
  18. 出租司机微软上MBA课 精辟理论让其月入1万6
  19. [AISTATS21]Towards Flexible Device Participation in Federated Learning阅读笔记
  20. ktt算法 约化_答:那些深度学习《面试》你可能需要知道的

热门文章

  1. 利用Fierce2查询子域名
  2. 摩拜上海涨价,已成全国最贵单车,一月运维花4亿全年亏45亿
  3. 儿童高脚椅、餐椅安全标准ASTM F404
  4. 【C++学习】 设计案例1:设计立方体类
  5. 利用FFmpeg玩转Android视频录制与压缩(三)
  6. 爬虫入门实践之爬取虎扑论坛帖子
  7. 带你解析微信公众号灵魂有香气的女子的创始人李筱懿
  8. 华强北3代耳机介绍,华强北耳机可靠吗?值得买吗?哪里买?
  9. 疯狂Java讲义(七)----第三部分
  10. 幻读和不可重复读的区别