編輯:關於Android編程
最近做了一個百度地圖離線地圖的功能,雖然功能實現了,但過程中也碰到了一些問題。首先,看看效果圖吧。
API地址:http://wiki.lbsyun.baidu.com/cms/androidsdk/doc/v4_0_0/index.html
MKOfflineMap類
主要的一個類,提供了離線地圖的管理功能,例如,下載,暫停、更新,刪除等功能。每次只允許一個下載任務進行,後面的需要排隊。
void destroy()MKOLSearchRecord類
離線地圖搜索城市記錄結構
java.util.ArrayList< MKOLSearchRecord> childCitiesMKOLUpdateElement類
離線地圖更新信息,下面是其中的一些字段
int cityIDMKOfflineMapListener接口
該接口返回新安裝離線地圖、下載更新、數據版本更新等結果,用戶需要實現該接口以處理相應事件。裡面有一個唯一的方法:
void onGetOfflineMapState(int type, int state) 返回通知事件OfflineActivity類
/* 此Demo用來演示離線地圖的下載和顯示 */
public class OfflineActivity extends Activity implements MKOfflineMapListener {
private MKOfflineMap mOffline = null;
private TextView cidView;
private TextView stateView;
private EditText cityNameView;
private HashMap hashMap = new HashMap(); //是否已下載;
private CityExpandableListAdapter adapter;
private HotcityListAdapter hAdapter;
private OfflineHandler offlineHandler;
private MKOLSearchRecord currentRecord;
private ArrayList loadingList = new ArrayList();
private ArrayList loadedList = new ArrayList();
public HashMap clickMap;
/**
* 已下載的離線地圖信息列表
*/
public ArrayList localMapList = null;
private LocalMapAdapter lAdapter = null;
private loadingMapAdapter dAdapter = null;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_offline);
ImageButton back = (ImageButton) findViewById(R.id.back);
back.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
OfflineActivity.this.finish();
}
});
offlineHandler = new OfflineHandler(this);
mOffline = new MKOfflineMap();
mOffline.init(this);
initView();
initCurLocation();
}
LocationManager lm = null; // location管理器
LocationClient mLocClient;
private void initCurLocation()
{
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (lm != null) {
// 定位初始化
mLocClient = new LocationClient(this);
mLocClient.registerLocationListener(new MyLocationListenner());
LocationClientOption option = new LocationClientOption();
option.setOpenGps(true);// 打開gps
option.setCoorType("bd09ll"); // 設置坐標類型
option.setPriority(LocationClientOption.NetWorkFirst);//設置網絡優先(不設置,默認是gps優先)
option.setAddrType("all");// 返回的定位結果包含地址信息
option.setScanSpan(10000);// 設置發起定位請求的間隔時間為10s(小於1秒則一次定位)
mLocClient.setLocOption(option);
mLocClient.start();
}else {
SystemUtil.showMessage("請打開GPS定位設置");
}
}
public void setCurrentLocation(String currentLocation) {
TextView current = (TextView) findViewById(R.id.current_name);
current.setText(currentLocation);
currentRecord = search(currentLocation);
RelativeLayout currentItem = (RelativeLayout)findViewById(R.id.current_item);
currentItem.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (hashMap.get(currentRecord.cityName))
{
Toast.makeText(OfflineActivity.this, "離線地圖已下載", Toast.LENGTH_LONG).show();
}else {
TextView currentSize = (TextView) v.findViewById(R.id.current_size);
currentSize.setText("正在下載");
start(currentRecord.cityID);
}
}
});
}
public class MyLocationListenner implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
MyLocationData locData = new MyLocationData.Builder()
.accuracy(location.getRadius())
// 此處設置開發者獲取到的方向信息,順時針0-360
.direction(100).latitude(location.getLatitude())
.longitude(location.getLongitude()).build();
String address=location.getAddrStr();
String city=location.getCity();
// System.out.println("地址:"+address+"城市:"+city);
setCurrentLocation(city);
}
public void onReceivePoi(BDLocation poiLocation) {
}
}
private void initView() {
// 獲取已下過的離線地圖信息
localMapList = mOffline.getAllUpdateInfo();
if (localMapList == null) {
localMapList = new ArrayList();
}
ListView localMapListView = (ListView) findViewById(R.id.localmaplist);
lAdapter = new LocalMapAdapter();
localMapListView.setAdapter(lAdapter);
ListView loadingListView = (ListView)findViewById(R.id.lodinglist);
dAdapter = new loadingMapAdapter();
loadingListView.setAdapter(dAdapter);
// cidView = (TextView) findViewById(R.id.cityid);
// cityNameView = (EditText) findViewById(R.id.city);
// stateView = (TextView) findViewById(R.id.state);
ListView hotCityList = (ListView) findViewById(R.id.hotcitylist);
final ArrayList hotCities = new ArrayList();
// 獲取熱門城市列表
final ArrayList records1 = mOffline.getHotCityList();
if (records1 != null) {
for (MKOLSearchRecord r : records1) {
hotCities.add(r.cityID);
}
}
hAdapter = new HotcityListAdapter(this, records1,hashMap);
hotCityList.setAdapter(hAdapter);
hotCityList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
if (hashMap.get(records1.get(position).cityName))
{
Toast.makeText(OfflineActivity.this, "離線地圖已下載", Toast.LENGTH_LONG).show();
}else {
TextView childSize = (TextView) view.findViewById(R.id.child_size);
childSize.setText("正在下載");
start(records1.get(position).cityID);
}
}
});
ExpandableListView allCityList = (ExpandableListView) findViewById(R.id.allcitylist);
// 獲取所有支持離線地圖的城市
final ArrayList records2 = mOffline.getOfflineCityList();
clickMap = new HashMap();
if (records1 != null) {
for (MKOLSearchRecord r : records2) {
// allCities.add(r.cityName+"--" + this.formatDataSize(r.size));
// allCitiyIds.add(r.cityID);
hashMap.put(r.cityName,downList(r.cityName));
clickMap.put(r.cityName, "0");
if (r.childCities != null && r.childCities.size() != 0)
{
ArrayList childrecord = r.childCities;
//
for (MKOLSearchRecord cr : childrecord)
{
hashMap.put(cr.cityName,downList(cr.cityName));
}
}
}
}
adapter = new CityExpandableListAdapter(this,records2,hashMap);
allCityList.setAdapter(adapter);
allCityList.setGroupIndicator(null);
hAdapter.notifyDataSetChanged();
allCityList.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
if (records2 != null )
{
MKOLSearchRecord record = records2.get(groupPosition);
if (record.childCities == null)
{
if (hashMap.get(record.cityName))
{
Toast.makeText(OfflineActivity.this, "離線地圖已下載", Toast.LENGTH_LONG).show();
}else
{
// System.out.println("simplename:"+v.getClass().getSimpleName());
int cd = record.cityID;
start(cd);
/* int size = ((ViewGroup)v).getChildCount();
for (int i = 0 ; i< size; i++)
{
View child = ((ViewGroup)v).getChildAt(i);
System.out.println("simplename:"+child.getClass().getSimpleName());
}
View child = ((ViewGroup)v).getChildAt(1);
((TextView)child).setText("正在下載");*/
clickMap.put(record.cityName, "1");
// adapter.notifyDataSetChanged();
}
}
}
return false;
}
});
allCityList.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
if (records2 != null)
{
MKOLSearchRecord record = records2.get(groupPosition);
MKOLSearchRecord cldred = record.childCities.get(childPosition);
if (hashMap.get(cldred.cityName))
{
Toast.makeText(OfflineActivity.this, "離線地圖已下載", Toast.LENGTH_LONG).show();
}else {
TextView childSize = (TextView) v.findViewById(R.id.child_size);
childSize.setText("正在下載");
start(cldred.cityID);
}
}
return false;
}
});
LinearLayout cl = (LinearLayout) findViewById(R.id.citylist_layout);
LinearLayout lm = (LinearLayout) findViewById(R.id.localmap_layout);
lm.setVisibility(View.GONE);
cl.setVisibility(View.VISIBLE);
}
public boolean downList(String cityName)
{
Boolean flag = false;
if (localMapList != null)
{
for (int i = 0; i records = mOffline.searchCity(city);
if (records == null || records.size() != 1) {
return null;
}
// cidView.setText(String.valueOf(records.get(0).cityID));
TextView current_size = (TextView) findViewById(R.id.current_size);
if (hashMap.get(records.get(0).cityName))
{
current_size.setText("已下載");
}else {
current_size.setText(formatDataSize(records.get(0).size));
}
return records.get(0);
}
/**
* 開始下載
*
* @param
*/
public void start(int cityid) {
// int cityid = Integer.parseInt(cidView.getText().toString());
mOffline.start(cityid);
clickLocalMapListButton(null);
// Toast.makeText(this, "開始下載離線地圖. cityid: " + cityid, Toast.LENGTH_SHORT).show();
updateView(null, false);
}
/**
* 暫停下載
*
* @param view
*/
public void stop(View view) {
int cityid = Integer.parseInt(cidView.getText().toString());
mOffline.pause(cityid);
Toast.makeText(this, "暫停下載離線地圖. cityid: " + cityid, Toast.LENGTH_SHORT)
.show();
updateView(null, false);
}
/**
* 刪除離線地圖
*
* @param view
*/
public void remove(View view) {
int cityid = Integer.parseInt(cidView.getText().toString());
mOffline.remove(cityid);
Toast.makeText(this, "刪除離線地圖. cityid: " + cityid, Toast.LENGTH_SHORT)
.show();
updateView(null,false);
}
/**
* 更新狀態顯示
*/
public void updateView(MKOLUpdateElement element, boolean flag) {
localMapList = mOffline.getAllUpdateInfo();
if (localMapList == null) {
localMapList = new ArrayList();
}
loadingList.clear();
loadedList.clear();
for (MKOLUpdateElement element1 : localMapList)
{
if (element1.ratio != 100)
{
loadingList.add(element1);
}else {
loadedList.add(element1);
}
}
if (element != null)
{
hashMap.put(element.cityName, flag);
if (currentRecord.cityID == element.cityID)
{
TextView currentSize = (TextView) findViewById(R.id.current_size);
if(flag)
{
currentSize.setText("已下載");
}else {
currentSize.setText(formatDataSize(element.size));
}
}else {
adapter.notifyDataSetChanged();
hAdapter.notifyDataSetChanged();
}
}
lAdapter.notifyDataSetChanged();
dAdapter.notifyDataSetChanged();
}
@Override
protected void onPause() {
// int cityid = Integer.parseInt(cidView.getText().toString());
// MKOLUpdateElement temp = mOffline.getUpdateInfo(cityid);
// if (temp != null && temp.status == MKOLUpdateElement.DOWNLOADING) {
// mOffline.pause(cityid);
// }
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
}
public String formatDataSize(int size) {
String ret = "";
if (size < (1024 * 1024)) {
ret = String.format("%dK", size / 1024);
} else {
ret = String.format("%.1fM", size / (1024 * 1024.0));
}
return ret;
}
@Override
protected void onDestroy() {
/**
* 退出時,銷毀離線地圖模塊
*/
mOffline.destroy();
super.onDestroy();
}
@Override
public void onGetOfflineMapState(int type, int state) {
switch (type) {
case MKOfflineMap.TYPE_DOWNLOAD_UPDATE: {
MKOLUpdateElement update = mOffline.getUpdateInfo(state);
// 處理下載進度更新提示
if (update != null) {
// stateView.setText(String.format("%s : %d%%", update.cityName,
// update.ratio));
// System.out.println("ratio:"+update.ratio);
if (update.ratio == 100)
{
updateView(update,true);
}else {
updateView(null, false);
}
}
}
break;
case MKOfflineMap.TYPE_NEW_OFFLINE:
// 有新離線地圖安裝
Log.d("OfflineDemo", String.format("add offlinemap num:%d", state));
break;
case MKOfflineMap.TYPE_VER_UPDATE:
// 版本更新提示
// MKOLUpdateElement e = mOffline.getUpdateInfo(state);
break;
default:
break;
}
}
/**
* 正在下載城市列表適配器
*/
public class loadingMapAdapter extends BaseAdapter{
@Override
public int getCount() {
return loadingList.size();
}
@Override
public Object getItem(int position) {
return loadingList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
{
convertView = LayoutInflater.from(OfflineActivity.this).inflate(R.layout.loding_list, null);
}
TextView name = (TextView) convertView.findViewById(R.id.city_name);
TextView size = (TextView)convertView.findViewById(R.id.city_size);
TextView ratio = (TextView)convertView.findViewById(R.id.down_ratio);
ImageButton manager= (ImageButton) convertView.findViewById(R.id.down_manager);
final MKOLUpdateElement ele = loadingList.get(position);
name.setText(ele.cityName);
size.setText(formatDataSize(ele.size));
ratio.setText(ele.ratio+"%");
manager.setOnClickListener(new OnClickListener() {
boolean flag = true;
@Override
public void onClick(View v) {
if (flag) {
mOffline.pause(ele.cityID);
v.setBackgroundResource(R.drawable.loading_start);
flag = false;
}else {
mOffline.start(ele.cityID);
v.setBackgroundResource(R.drawable.loading_pause);
flag = true;
}
}
});
return convertView;
}
}
/**
* 離線地圖管理列表適配器
*/
public class LocalMapAdapter extends BaseAdapter {
@Override
public int getCount() {
return loadedList.size();
}
@Override
public Object getItem(int index) {
return loadedList.get(index);
}
@Override
public long getItemId(int index) {
return index;
}
@Override
public View getView(int index, View view, ViewGroup arg2) {
MKOLUpdateElement e = (MKOLUpdateElement) getItem(index);
view = View.inflate(OfflineActivity.this,
R.layout.offline_localmap_list, null);
initViewItem(view, e);
return view;
}
void initViewItem(View view, final MKOLUpdateElement e) {
Button remove = (Button) view.findViewById(R.id.remove);
TextView title = (TextView) view.findViewById(R.id.title);
TextView update = (TextView) view.findViewById(R.id.update);
// TextView ratio = (TextView) view.findViewById(R.id.ratio);
Button doUpdate = (Button) view.findViewById(R.id.exe_update);
// ratio.setText(e.ratio + "%");
title.setText(e.cityName);
if (e.update) {
update.setText("可更新");
} else {
update.setText("最新");
}
remove.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
mOffline.remove(e.cityID);
clickMap.put(e.cityName,"0");
updateView(e, false);
}
});
doUpdate.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mOffline.update(e.cityID);
}
});
}
}
}
布局文件activity_offline.xml
CityExpandableListAdapter類
public class CityExpandableListAdapter extends BaseExpandableListAdapter {
private OfflineActivity context;
private ArrayList records;
private HashMap hashMap;
public CityExpandableListAdapter(OfflineActivity context, ArrayList records, HashMap hashMap)
{
this.context = context;
this.records = records;
this.hashMap = hashMap;
System.out.println("hashMapsize:"+hashMap.size());
}
@Override
public int getGroupCount() {
return records.size();
}
@Override
public int getChildrenCount(int groupPosition) {
if (records.get(groupPosition).childCities != null)
{
return records.get(groupPosition).childCities.size();
}
return 0;
}
@Override
public Object getGroup(int groupPosition) {
return records.get(groupPosition);
}
@Override
public Object getChild(int groupPosition, int childPosition) {
if (records.get(groupPosition).childCities != null)
{
return records.get(groupPosition).childCities.get(childPosition);
}
return null;
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
GroupHolder groupHolder = null;
if (convertView == null)
{
convertView = LayoutInflater.from(context).inflate(R.layout.expandlist_group, parent, false);
groupHolder = new GroupHolder();
groupHolder.txt = (TextView)convertView.findViewById(R.id.names);
groupHolder.size = (TextView)convertView.findViewById(R.id.map_size);
groupHolder.img = (ImageView)convertView.findViewById(R.id.indicator_arrow);
convertView.setTag(groupHolder);
}
else
{
groupHolder = (GroupHolder)convertView.getTag();
}
String cityName = records.get(groupPosition).cityName;
groupHolder.txt.setText(cityName);
if (records.get(groupPosition).childCities == null)
{
groupHolder.img.setVisibility(View.GONE);
groupHolder.size.setVisibility(View.VISIBLE);
if (hashMap.get(cityName))
{
groupHolder.size.setText("已下載");
}else {
if ("1".equals(context.clickMap.get(cityName)))
{
groupHolder.size.setText("正在下載");
}else {
groupHolder.size.setText(context.formatDataSize(records.get(groupPosition).size));
}
}
}else {
groupHolder.size.setVisibility(View.GONE);
groupHolder.img.setVisibility(View.VISIBLE);
}
//判斷isExpanded就可以控制是按下還是關閉,同時更換圖片
if(isExpanded){
groupHolder.img.setBackgroundResource(R.drawable.moreitems_arrow);
}else{
groupHolder.img.setBackgroundResource(R.drawable.moreitems_arrow_down); }
return convertView;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
ItemHolder itemHolder = null;
if (convertView == null)
{
// convertView = convertView.inflate(context, R.layout.expandlist_item, null);
convertView = LayoutInflater.from(context).inflate(R.layout.expandlist_item, parent,false);
itemHolder = new ItemHolder();
itemHolder.txt = (TextView)convertView.findViewById(R.id.child_names);
itemHolder.size = (TextView)convertView.findViewById(R.id.child_size);
// itemHolder.img = (ImageView)convertView.findViewById(R.id.img);
convertView.setTag(itemHolder);
}
else
{
itemHolder = (ItemHolder)convertView.getTag();
}
if (records.get(groupPosition).childCities != null)
{
ArrayList list = records.get(groupPosition).childCities;
if (list.size()>0)
{
MKOLSearchRecord info = list.get(childPosition);
String cityName = info.cityName;
itemHolder.txt.setText(cityName);
if (hashMap.get(cityName))
{
itemHolder.size.setText("已下載");
}else {
itemHolder.size.setText(context.formatDataSize(info.size));
}
}
}
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
class GroupHolder
{
public TextView txt;
public TextView size;
public ImageView img;
}
class ItemHolder
{
public ImageView img;
public TextView size;
public TextView txt;
}
}
3、遇到的問題
關於ExpandableListview
在setOnGroupClickListener中修改group上TextView的文字時無效;
View child = ((ViewGroup)v).getChildAt(1);
((TextView)child).setText(“正在下載”)
這樣設置沒有效果,但是在setOnChildClickListener上做類似的修改是有效的,這裡在點擊group時,好像setOnGroupClickListener去調用了adapter的notifyDataSetChanged(),但是在程序中沒找到,難道這是默認行為?
最後還是通過下面的方法解決
clickMap.put(record.cityName, “1”);
adapter.notifyDataSetChanged();
通過修改數據,然後調用adapter.notifyDataSetChanged();在adapter中進行修改;
在item根部局上設置minHeight屬性可以有效的設置item的高度。
LayoutInflater類的infalter方法,幾種重載方法的區別:
之前對這個有所了解,這裡碰到的時候又忘記了,再次記錄下。
1. 如果root為null,attachToRoot將失去作用,設置任何值都沒有意義。
2. 如果root不為null,attachToRoot設為true,則會給加載的布局文件的指定一個父布局,即root。
3. 如果root不為null,attachToRoot設為false,則會將布局文件最外層的所有layout屬性進行設置,當該view被添加到父view當中時,這些layout屬性會自動生效。
4. 在不設置attachToRoot參數的情況下,如果root不為null,attachToRoot參數默認為true。
前言在一些APP中我們可以看到一些存放標簽的容器控件,和我們平時使用的一些布局方式有些不同,它們一般都可以自動適應屏幕的寬度進行布局,根據對自定義控件的一些理解,今天寫一
MAT(Memory Analyzer Tool), 是著名的Android內存分析工具, 雖然LeakCanary更加便捷, 但是MAT可以清楚地獲知整體內存使用情況,
Intent簡介Android中提供了Intent機制來協助應用間的交互與通訊,Intent負責對應用中一次操作的動作、動作涉及數據、附加數據進行描述,Android則根
本文實例講述了Android編程開發之seekBar采用handler消息處理操作的方法。分享給大家供大家參考,具體如下:該案例簡單實現進度條可走,可拖拽的功能,下面請看