仿美團實現城市定位。
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 android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
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.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast; import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.droid.MyLetterListView.OnTouchingLetterChangedListener; public class Activity01 extends Activity implements OnScrollListener {
private BaseAdapter adapter;
private ResultListAdapter resultListAdapter;
private ListView personList;
private ListView resultList;//搜尋結果列表
private TextView overlay; // 對話方塊首字母textview
private MyLetterListView letterListView; // A-Z listview
private HashMap<String, Integer> alphaIndexer;// 存放存在的漢語拼音首字母和與之對應的列表位置
private String[] sections;// 存放存在的漢語拼音首字母
private Handler handler;
private OverlayThread overlayThread; // 顯示首字母對話方塊
private ArrayList<City> allCity_lists; // 所有城市列表
private ArrayList<City> city_lists;// 城市列表
private ArrayList<City> city_hot;//熱門城市列表
private ArrayList<City> city_result;//城市結果
private ArrayList<String> city_history;//歷史城市結果
private EditText sh; //搜尋框
private TextView tv_noresult; //顯示搜尋結果
//定位
private LocationClient mLocationClient;
private MyLocationListener mMyLocationListener;
public TextView city;
private String currentCity; // 用於儲存定位到的城市
private int locateProcess = 1; // 記錄當前定位的狀態 正在定位(1)-定位成功(2)-定位失敗(3)
//是否需要新的
private boolean isNeedFresh;
//我們從檔案的全國城市列表
private DatabaseHelper helper; @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
personList = (ListView) findViewById(R.id.list_view);
allCity_lists = new ArrayList<City>();
city_hot = new ArrayList<City>();
city_result = new ArrayList<City>();
city_history = new ArrayList<String>();
resultList = (ListView) findViewById(R.id.search_result);
sh = (EditText) findViewById(R.id.sh);
//沒有該城市的搜尋結果出現該提示訊息
tv_noresult = (TextView) findViewById(R.id.tv_noresult);
helper = new DatabaseHelper(this);
//城市搜尋框增加監聽器
sh.addTextChangedListener(new TextWatcher() { @Override
//文字改變前呼叫的方法
//這個方法被呼叫,說明在s字串中,從start位置開始的count個字元即將被長度為after的新文字所取代。在這個方法裡面改變s,會報錯。
public void onTextChanged(CharSequence s, int start, int before,
int count) {
if (s.toString() == null || "".equals(s.toString())) {
//View預設(預設)為可見的,在應用可以通過setVisibility 修改View的可見性,View可用性可以有如下三種狀態:
//View.VISIBLE View可見
//View.INVISIBLE View不可以見,但仍然佔據可見時的大小和位置。
//View.GONE View不可見,且不佔據空間
letterListView.setVisibility(View.VISIBLE);
personList.setVisibility(View.VISIBLE);
resultList.setVisibility(View.GONE);
tv_noresult.setVisibility(View.GONE);
} else {
//保證下一次進來搜尋頁面,不會保留上一次的搜尋結果
city_result.clear();
letterListView.setVisibility(View.GONE);
personList.setVisibility(View.GONE);
getResultCityList(s.toString());
if (city_result.size() <= 0) {
tv_noresult.setVisibility(View.VISIBLE);
resultList.setVisibility(View.GONE);
} else {
tv_noresult.setVisibility(View.GONE);
resultList.setVisibility(View.VISIBLE);
resultListAdapter.notifyDataSetChanged();
}
}
} @Override
//文字呼叫時的方法
// //這個方法被呼叫,說明在s字串中,從start位置開始的count個字元剛剛取代了長度為before的舊文字。在這個方法裡面改變
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
} @Override
//方放呼叫完成後的方法
//這個方法被呼叫,那麼說明s字串的某個地方已經被改變。 public void afterTextChanged(Editable s) { }
});
letterListView = (MyLetterListView) findViewById(R.id.MyLetterListView01);
letterListView
.setOnTouchingLetterChangedListener(new LetterListViewListener());
//字母表的角標,t
alphaIndexer = new HashMap<String, Integer>();
handler = new Handler();
overlayThread = new OverlayThread();
isNeedFresh = true;
//城市列表的item點選事件
personList.setOnItemClickListener(new OnItemClickListener() { @Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
if (position >= 4) {
Toast.makeText(getApplicationContext(),
allCity_lists.get(position).getName(),
Toast.LENGTH_SHORT).show();
}
}
});
locateProcess = 1;
personList.setAdapter(adapter);
personList.setOnScrollListener(this);
resultListAdapter = new ResultListAdapter(this, city_result);
resultList.setAdapter(resultListAdapter);
resultList.setOnItemClickListener(new OnItemClickListener() { @Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(getApplicationContext(),
city_result.get(position).getName(), Toast.LENGTH_SHORT)
.show();
}
});
//首字母索引的方法
initOverlay();
//初始化城市
cityInit();
//初始化熱門城市
hotCityInit();
//初始化曾經搜尋過的城市
hisCityInit();
setAdapter(allCity_lists, city_hot, city_history); mLocationClient = new LocationClient(this.getApplicationContext());
mMyLocationListener = new MyLocationListener();
mLocationClient.registerLocationListener(mMyLocationListener);
//對定位進行初始化
InitLocation();
//開始定位
mLocationClient.start();
}
//對城市資訊進行插入操作
public void InsertCity(String name) {
SQLiteDatabase db = helper.getReadableDatabase();
Cursor cursor = db.rawQuery("select * from recentcity where name = '"
+ name + "'", null);
if (cursor.getCount() > 0) { //
db.delete("recentcity", "name = ?", new String[] { name });
}
db.execSQL("insert into recentcity(name, date) values('" + name + "', "
+ System.currentTimeMillis() + ")");
db.close();
} private void InitLocation() {
// 設定定位引數
LocationClientOption option = new LocationClientOption();
option.setCoorType("bd09ll"); // 設定座標型別
option.setScanSpan(10000); // 10分鐘掃描1次
// 需要地址資訊,設定為其他任何值(string型別,且不能為null)時,都表示無地址資訊。
option.setAddrType("all");
// 設定是否返回POI的電話和地址等詳細資訊。預設值為false,即不返回POI的電話和地址資訊。
option.setPoiExtraInfo(true);
// 設定產品線名稱。強烈建議您使用自定義的產品線名稱,方便我們以後為您提供更高效準確的定位服務。
option.setProdName("通過GPS定位我當前的位置");
// 禁用啟用快取定位資料
option.disableCache(true);
// 設定最多可返回的POI個數,預設值為3。由於POI查詢比較耗費流量,設定最多返回的POI個數,以便節省流量。
option.setPoiNumber(3);
// 設定定位方式的優先順序。
// 當gps可用,而且獲取了定位結果時,不再發起網路請求,直接返回給使用者座標。這個選項適合希望得到準確座標位置的使用者。如果gps不可用,再發起網路請求,進行定位。
option.setPriority(LocationClientOption.GpsFirst);
mLocationClient.setLocOption(option);
}
//城市資訊的初始化處
private void cityInit() {
City city = new City("定位", "0"); // 當前定位城市
allCity_lists.add(city);
city = new City("最近", "1"); // 最近訪問的城市
allCity_lists.add(city);
city = new City("熱門", "2"); // 熱門城市
allCity_lists.add(city);
city = new City("全部", "3"); // 全部城市
allCity_lists.add(city);
city_lists = getCityList();
allCity_lists.addAll(city_lists);
} /**
* 熱門城市
*/
//city方法中引數的"2"應該是設定在拼音檢索中的優先順序
//可以在這方法中自己新增熱門城市的資訊
public void hotCityInit() {
City city = new City("上海", "2");
city_hot.add(city);
city = new City("北京", "2");
city_hot.add(city);
city = new City("廣州", "2");
city_hot.add(city);
city = new City("深圳", "2");
city_hot.add(city);
city = new City("武漢", "2");
city_hot.add(city);
city = new City("天津", "2");
city_hot.add(city);
city = new City("西安", "2");
city_hot.add(city);
city = new City("南京", "2");
city_hot.add(city);
city = new City("杭州", "2");
city_hot.add(city);
city = new City("成都", "2");
city_hot.add(city);
city = new City("重慶", "2");
city_hot.add(city);
city = new City("吉安", "2");
city_hot.add(city);
} private void hisCityInit() {
SQLiteDatabase db = helper.getReadableDatabase();
Cursor cursor = db.rawQuery(
"select * from recentcity order by date desc limit 0, 3", null);
while (cursor.moveToNext()) {
city_history.add(cursor.getString(1));
}
cursor.close();
db.close();
} @SuppressWarnings("unchecked")
private ArrayList<City> getCityList() {
DBHelper dbHelper = new DBHelper(this);
ArrayList<City> list = new ArrayList<City>();
try {
dbHelper.createDataBase();
SQLiteDatabase db = dbHelper.getWritableDatabase();
Cursor cursor = db.rawQuery("select * from city", null);
City city;
while (cursor.moveToNext()) {
city = new City(cursor.getString(1), cursor.getString(2));
list.add(city);
}
cursor.close();
db.close();
} catch (IOException e) {
e.printStackTrace();
}
Collections.sort(list, comparator);
return list;
} @SuppressWarnings("unchecked")
private void getResultCityList(String keyword) {
DBHelper dbHelper = new DBHelper(this);
try {
dbHelper.createDataBase();
SQLiteDatabase db = dbHelper.getWritableDatabase();
Cursor cursor = db.rawQuery(
"select * from city where name like \"%" + keyword
+ "%\" or pinyin like \"%" + keyword + "%\"", null);
City city;
Log.e("info", "length = " + cursor.getCount());
while (cursor.moveToNext()) {
city = new City(cursor.getString(1), cursor.getString(2));
city_result.add(city);
}
cursor.close();
db.close();
} catch (IOException e) {
e.printStackTrace();
}
Collections.sort(city_result, comparator);
} /**
* a-z排序
*/
@SuppressWarnings("rawtypes")
Comparator comparator = new Comparator<City>() {
@Override
public 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;
}
}
}; private void setAdapter(List<City> list, List<City> hotList,
List<String> hisCity) {
adapter = new ListAdapter(this, list, hotList, hisCity);
personList.setAdapter(adapter);
} /**
* 實現實位回撥監聽
*/
public class MyLocationListener implements BDLocationListener { @Override
public void onReceiveLocation(BDLocation arg0) {
Log.e("info", "city = " + arg0.getCity());
if (!isNeedFresh) {
return;
}
isNeedFresh = false;
if (arg0.getCity() == null) {
locateProcess = 3; // 定位失敗
personList.setAdapter(adapter);
adapter.notifyDataSetChanged();
return;
}
currentCity = arg0.getCity().substring(0,
arg0.getCity().length() - 1);
locateProcess = 2; // 定位成功
personList.setAdapter(adapter);
adapter.notifyDataSetChanged();
} @Override
public void onReceivePoi(BDLocation arg0) { }
} private class ResultListAdapter extends BaseAdapter {
private LayoutInflater inflater;
private ArrayList<City> results = new ArrayList<City>(); public ResultListAdapter(Context context, ArrayList<City> results) {
inflater = LayoutInflater.from(context);
this.results = results;
} @Override
public int getCount() {
return results.size();
} @Override
public Object getItem(int position) {
return position;
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_item, null);
viewHolder = new ViewHolder();
viewHolder.name = (TextView) convertView
.findViewById(R.id.name);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.name.setText(results.get(position).getName());
return convertView;
} class ViewHolder {
TextView name;
}
} public class ListAdapter extends BaseAdapter {
private Context context;
private LayoutInflater inflater;
private List<City> list;
private List<City> hotList;
private List<String> hisCity;
final int VIEW_TYPE = 5; public ListAdapter(Context context, List<City> list,
List<City> hotList, List<String> hisCity) {
this.inflater = LayoutInflater.from(context);
this.list = list;
this.context = context;
this.hotList = hotList;
this.hisCity = hisCity;
alphaIndexer = new HashMap<String, Integer>();
sections = new String[list.size()];
for (int i = 0; i < list.size(); i++) {
// 當前漢語拼音首字母
String currentStr = getAlpha(list.get(i).getPinyi());
// 上一個漢語拼音首字母,如果不存在為" "
String previewStr = (i - 1) >= 0 ? getAlpha(list.get(i - 1)
.getPinyi()) : " ";
if (!previewStr.equals(currentStr)) {
String name = getAlpha(list.get(i).getPinyi());
alphaIndexer.put(name, i);
sections[i] = name;
}
}
} @Override
public int getViewTypeCount() {
return VIEW_TYPE;
} @Override
public int getItemViewType(int position) {
return position < 4 ? position : 4;
} @Override
public int getCount() {
return list.size();
} @Override
public Object getItem(int position) {
return list.get(position);
} @Override
public long getItemId(int position) {
return position;
} ViewHolder holder; @Override
public View getView(int position, View convertView, ViewGroup parent) {
int viewType = getItemViewType(position);
if (viewType == 0) { // 定位
convertView = inflater.inflate(R.layout.frist_list_item, null);
//定位的資訊/提示
TextView locateHint = (TextView) convertView
.findViewById(R.id.locateHint);
//定位城市的資訊,例如你在廣州,這個textView顯示的就是廣州
city = (TextView) convertView.findViewById(R.id.lng_city);
city.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//如果定位成功的話
if (locateProcess == 2) { Toast.makeText(getApplicationContext(),
city.getText().toString(),
Toast.LENGTH_SHORT).show();
}
//如果定位失敗的話,我們把定位狀態在切換到正在定位
//一般我們出現的定位失敗的情況都是未開啟網路或者wifl或者gps
else if (locateProcess == 3) {
locateProcess = 1;
personList.setAdapter(adapter);
//重新整理我們列表
adapter.notifyDataSetChanged();
mLocationClient.stop();
//重新整理為新的
isNeedFresh = true;
InitLocation();
//當我們的定位城市資訊列表為空的時候,我們繼續開啟定位
currentCity = "";
mLocationClient.start();
}
}
});
//我們定位中等待的icon圖示
ProgressBar pbLocate = (ProgressBar) convertView
.findViewById(R.id.pbLocate);
if (locateProcess == 1) { // 正在定位
locateHint.setText("正在定位");
city.setVisibility(View.GONE);
pbLocate.setVisibility(View.VISIBLE);
} else if (locateProcess == 2) { // 定位成功
locateHint.setText("當前定位城市");
city.setVisibility(View.VISIBLE);
city.setText(currentCity);
mLocationClient.stop();
pbLocate.setVisibility(View.GONE);
} else if (locateProcess == 3) {
locateHint.setText("未定位到城市,請選擇");
city.setVisibility(View.VISIBLE);
city.setText("重新選擇");
pbLocate.setVisibility(View.GONE);
}
} else if (viewType == 1) { // 最近訪問城市
convertView = inflater.inflate(R.layout.recent_city, null);
GridView rencentCity = (GridView) convertView
.findViewById(R.id.recent_city);
rencentCity
.setAdapter(new HitCityAdapter(context, this.hisCity));
rencentCity.setOnItemClickListener(new OnItemClickListener() { @Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) { Toast.makeText(getApplicationContext(),
city_history.get(position), Toast.LENGTH_SHORT)
.show(); }
});
TextView recentHint = (TextView) convertView
.findViewById(R.id.recentHint);
recentHint.setText("最近訪問的城市");
} else if (viewType == 2) {
convertView = inflater.inflate(R.layout.recent_city, null);
GridView hotCity = (GridView) convertView
.findViewById(R.id.recent_city);
hotCity.setOnItemClickListener(new OnItemClickListener() { @Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) { Toast.makeText(getApplicationContext(),
city_hot.get(position).getName(),
Toast.LENGTH_SHORT).show(); }
});
hotCity.setAdapter(new HotCityAdapter(context, this.hotList));
TextView hotHint = (TextView) convertView
.findViewById(R.id.recentHint);
hotHint.setText("熱門城市");
} else if (viewType == 3) {
convertView = inflater.inflate(R.layout.total_item, null);
} else {
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 (position >= 1) {
holder.name.setText(list.get(position).getName());
String currentStr = getAlpha(list.get(position).getPinyi());
String previewStr = (position - 1) >= 0 ? getAlpha(list
.get(position - 1).getPinyi()) : " ";
if (!previewStr.equals(currentStr)) {
holder.alpha.setVisibility(View.VISIBLE);
//這裡是設定首字母的 比如 重慶 C首字母
holder.alpha.setText(currentStr);
} else {
holder.alpha.setVisibility(View.GONE);
}
}
}
return convertView;
} private class ViewHolder {
TextView alpha; // 首字母標題
TextView name; // 城市名字
}
} @Override
//封裝著定位停止的方法
protected void onStop() {
mLocationClient.stop();
super.onStop();
} class HotCityAdapter extends BaseAdapter {
private Context context;
private LayoutInflater inflater;
private List<City> hotCitys; public HotCityAdapter(Context context, List<City> hotCitys) {
this.context = context;
inflater = LayoutInflater.from(this.context);
this.hotCitys = hotCitys;
} @Override
public int getCount() {
return hotCitys.size();
} @Override
public Object getItem(int position) {
return position;
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = inflater.inflate(R.layout.item_city, null);
TextView city = (TextView) convertView.findViewById(R.id.city);
city.setText(hotCitys.get(position).getName());
return convertView;
}
} class HitCityAdapter extends BaseAdapter {
private Context context;
private LayoutInflater inflater;
private List<String> hotCitys; public HitCityAdapter(Context context, List<String> hotCitys) {
this.context = context;
inflater = LayoutInflater.from(this.context);
this.hotCitys = hotCitys;
} @Override
public int getCount() {
return hotCitys.size();
} @Override
public Object getItem(int position) {
return position;
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = inflater.inflate(R.layout.item_city, null);
TextView city = (TextView) convertView.findViewById(R.id.city);
city.setText(hotCitys.get(position));
return convertView;
}
} private boolean mReady; // 初始化漢語拼音首字母彈出提示框
private void initOverlay() {
mReady = true;
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 boolean isScroll = false; private class LetterListViewListener implements
OnTouchingLetterChangedListener { @Override
//overlay覆蓋物
public void onTouchingLetterChanged(final String s) {
isScroll = false;
if (alphaIndexer.get(s) != null) {
int position = alphaIndexer.get(s);
personList.setSelection(position);
overlay.setText(s);
overlay.setVisibility(View.VISIBLE);
handler.removeCallbacks(overlayThread);
// 延遲一秒後執行,讓overlay為不可見
handler.postDelayed(overlayThread, 1000);
}
}
} // 設定overlay不可見
private class OverlayThread implements Runnable {
@Override
public void run() {
overlay.setVisibility(View.GONE);
}
} // 獲得漢語拼音首字母
private String getAlpha(String str) {
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 if (str.equals("0")) {
return "定位";
} else if (str.equals("1")) {
return "最近";
} else if (str.equals("2")) {
return "熱門";
} else if (str.equals("3")) {
return "全部";
} else {
return "#";
}
} @Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_TOUCH_SCROLL
|| scrollState == SCROLL_STATE_FLING) {
isScroll = true;
}
} @Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (!isScroll) {
return;
} if (mReady) {
String text;
String name = allCity_lists.get(firstVisibleItem).getName();
String pinyin = allCity_lists.get(firstVisibleItem).getPinyi();
if (firstVisibleItem < 4) {
text = name;
} else {
text = PingYinUtil.converterToFirstSpell(pinyin)
.substring(0, 1).toUpperCase();
}
overlay.setText(text);
overlay.setVisibility(View.VISIBLE);
handler.removeCallbacks(overlayThread);
// 延遲一秒後執行,讓overlay為不可見
handler.postDelayed(overlayThread, 1000);
}
}
}