05、ListActivity的使用
第一个好处:处理共同的操作,避免代码重复
假设我要写第二个界面我也是需要使用到mapView,那你都要去查找一个mapView.都要获取一个Map的一个地图.
第二个好处:代码规范(方便阅读,真实开发80%的时间都是在阅读代码)
刚刚写的这个init()方法.以前你们用BaseActivity可能还有initView、initListener、initData.它就是一个规范.我就规范了你说如果说你这个子类要写初始化代码,你必须只能写到我的init方法里面去.这个叫规范.规范就预防了一些空指针的一些异常出现.规范就是方便你去阅读这个代码.只有20%的时间在写代码,80%的时间都是在读代码.因为你要修改,修改你要看哪里出BUG,就要阅读代码.或者说别人写好的代码你要去增加功能,那你肯定也要看一看别人代码怎么写的.读代码的时间会比你写代码的时间多得多.所以说如果你代码写的规范的话,那你开发的时间就会大大减小.比如说我们写了这个initView那你要看一些查找View的代码呢你就按一下Ctrl+O定位到那个initView()方法去看就行了.那个初始化View的代码呢肯定在那里面去了.这个叫规范.
第三个好处:可以提供一些常用变量、方法(方便调用,避免代码重复)
提供了有几个坐标.以后我的子类要想定位到一个什么坐标就可以用父类的这些坐标.这个叫提供一些常用的成员变量.
// 常量要放在最前面. private static final String TAG = "BaseActivity";//TAG一般以它类名. /** 黑马坐标(北京市海淀区东北旺南路45号) */ protected LatLng hmPos = new LatLng(40.050513, 116.30361);// LatLng的一个常量表示. /** 传智坐标 */ protected LatLng czPos = new LatLng(40.065817, 116.349902); /** 天安门坐标 */ protected LatLng tamPos = new LatLng(39.915112, 116.403963);
还有方法体现在哪里呢?有一个showToast的方法.那以后只要我想显示一个吐司,那我就不用写这堆代码了.我就调一下showToast这个方法.传一个字符串我就能把这个吐司显示到屏幕的中央.这个呢就是这一个好处,它其实也是方便我们调用.而且也可以说也避免了代码的一个重复.
/** * 在屏幕中央显示一个Toast * @param text */ public void showToast(CharSequence text){//字符序列.字符序列这个接口 //CharSequence其实是我们String的父类.String是实现了这个接口的. //所以说我们最好面向接口来编程.这样子这个方法更加通用. Toast toast = Toast.makeText(this, text, Toast.LENGTH_SHORT);//局部变量toast toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); }
如果说面试官没有问你为什么要抽取这个BaseActivity,你可以主动地去把它说出来.我抽取这个Base为什么要抽取呢?你可以把这三点跟他说一下.
因为这个市面上的很多这种开发人员,他们抽取这个BaseActivity他为什么要抽取呢?是因为他在写代码的时候几乎每一个公司他一过去肯定人家已经有一个BaseActivity了.那如果写的时候他也会搞一个,因为他不知道为什么他感觉别人都有BaseActivity,那我也搞一个.如果说我不搞一个Base会显得我自己呢很落后.但是如果你要是问他为什么要抽取一个BaseActivity他可能想不出什么功能来.想不出为什么要抽取.他可能就只能想到一个说避免代码的重复.他可能只想到一个.如果你面试的时候能把这三个都说出来,然后呢这三个体现在哪里刚刚我已经带大家看了体现在哪里.能大概把它说出来,那这个面试官呢会觉得你,哦,好专业.可能这个面试官他自己呢他也不清楚.你这么一说他就会觉得你很专业了.
OK,BaseActivity我们就抽取完成了.接下来我们还会写很多的这种百度地图的一些演示一些应用.很多的话我们要写很多Activity.那如果说你写一个按钮来点击进行跳转的话会比较麻烦,我们这里就写一个listview.listview进行跳转会比较简单.
介绍一下
DemoListActivity
面试的时候也可以去说一下,因为市面上呢很多开发人员他都不会用这个
ListActivity.他不去用这个ListActivity.
ListActivity用起来还是很简单的,你跟这个面试官去说你之前,比如说他问你请说一说这个四大组件.
那你说到Activity的时候就可以说我用过这个FragementActivity,用过ListenerActivity,用过TableHostActivity.假设一说他哎,这个Activity我没用过啊,他就会问这个Activity是干嘛的,它怎么用?那你一说把它说出来说的头头是道,这个面试官会觉得,哇,你这个好专业啊,这个东西你都懂.他又感觉他学到了东西,然后对你的印象呢也会比较好.
这个ListActivity很明显它是一个显示列表的Activity.显示一个列表,那你如果用它的话呢它就可以简化我们这个列表界面的开发.到底有多简化呢?
ListActivity里面已经封装了一个listview,所以说你用它的话会简化你的很多代码.
public class ListActivity extends Activity { /** * This field should be made private, so it is hidden from the SDK. * {@hide} */ protected ListAdapter mAdapter; /** * This field should be made private, so it is hidden from the SDK. * {@hide} */ protected ListView mList;
它有这样的一个方法onListItemClick
/** * This method will be called when an item in the list is selected. * Subclasses should override. Subclasses can call * getListView().getItemAtPosition(position) if they need to access the * data associated with the selected item. * * @param l The ListView where the click happened * @param v The view that was clicked within the ListView * @param position The position of the view in the list * @param id The row id of the item that was clicked */ protected void onListItemClick(ListView l, View v, int position, long id) { }
所以一会呢我们处理单击监听器的时候呢就覆盖一下它就行了.
如果说你们有时间你们自己看,完全看得懂ListActivity的源代码.因为源码才三百多行,你扣去这个空行再扣去这个注释,其实可能这个真实的代码可能不超过一百行.你看这个注释非常多,你把这些去除,那这个,你看前面就占了170几行.你把这些注释去掉,它真实的代码呢不会超过一百行.你自己去看完全看得懂.
有学过哪些Adapter的子类?ListAdapter.ArrayAdapte也学过.那这个就很好办了.ArrayAdapter它也是ListAdapter的一个子类.
运行之后的结果:
声明ArrayAdapter传的是类的一个对象,里面的数据是这样的一个对象:ClassAndName.那它打印的时候会打印什么呢?它就会打印你这个对象ClassAndName.我们说打印一个对象其实它打印的是,这个是属于java基础,比如说我调的是一个System.out来输出一个类.直接传一个类一个对象,那它最终输出的其实是一个toString().它打印的是我们的toString().
所以我们刚刚看到的内容其实它是显示的是toString().但是我们需要的是这个name这样的一个属性.是这样的一个属性.所以这里面我们可以直接返回这个name就行了.
@Override public String toString() {//打印ClassAndName的时候它就会调这个方法取这个字符串去显示. // TODO Auto-generated method stub return name; }
再次运行一次:
但是点击之后我们应该要打开那个Activity才可以啊.
//这个就很简单,你不用去注册什么监听器了.直接覆盖它的onListItemClick方法. //跟我们注册的那个方法可以说是一模一样. @Override protected void onListItemClick(ListView l, View v, int position, long id) { // TODO Auto-generated method stub //super.onListItemClick(l, v, position, id);//super是空实现,可以删除掉. //取出单击位置的对象 ClassAndName 取出之后你就能拿到这个字节码,让它跳转到这个字节码对应的Activity. //Object itemAtPosition = l.getItemAtPosition(position);//l就是listview.把position放进来. ClassAndName classAndName = (ClassAndName) l.getItemAtPosition(position);//其实它拿出来的是ClassAndName //startActivity(new Intent(this, classAndName.cls));//开启一个Activity.上下文传this.字节码从classAndName这里面去取就行了. startActivity(new Intent(this, classAndName.clazz)); }
DemoListActivity.java的真实代码行数是47行.回去做一个试验:你不用这个DemoListActivity.java然后呢你就用你平常的写法去写这样的一个列表,实现我们这样的一个效果,然后你看你这个代码会不会比DemoListActivity.java多很多.大家可以去尝试一下.在DemoListActivity.java里面我们发现没多少行就搞定了.
之前我们在HelloBaiduMapActivity.java里面有一个检查这个Key是否正常的一个广播.那现在我们这个应用一跑起来的时候你就应该去检测,就是还没有点击HelloBaiduMap的时候你就应该去检测.所以说我们这个注册广播应该放到DemoListActivity.java里面去.
@SuppressWarnings("unused") private void registerSDKCheckReceiver() { // 如果你不注册这个广播假设你这个key错了你也不知道.你可能会认为哪一步错了然后找很久找不到原因.所以我们最好去注册一下这样的一个广播. receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub // 如果说接收到广播就会跑到这里面来. // 这里面由于我们是有两个action,我们要进行一个判断,先把它们取出来. String action = intent.getAction(); if (SDKInitializer.SDK_BROADCAST_ACTION_STRING_NETWORK_ERROR .equals(action)) {// 首先是这个网络错误,. // 显示吐司这种代码很常用,如果说我们有一个base的话呢以后我们显示吐司会非常方便. // 这个base类大家应该不陌生. // 当我们接收到这一个网络处理故障的广播的时候呢, showToast("网络错误"); } else if (SDKInitializer.SDK_BROADTCAST_ACTION_STRING_PERMISSION_CHECK_ERROR .equals(action)) { showToast("key验证失败"); } } // 因为代码不会很多我就直接new它的内部类了. }; IntentFilter filter = new IntentFilter();// 本地变量,局部变量.IntentFilter是比较关键,也就是说你要拦截哪些广播就通过它来指定. // 监听网络错误 filter.addAction(SDKInitializer.SDK_BROADCAST_ACTION_STRING_NETWORK_ERROR);// 广播会以action的方式发出来.这个action从哪里来呢? // 我们最主要的还不是监听网络错误,我们需要的是权限检查的错误 // 监听百度地图sdk 的key是否正确. filter.addAction(SDKInitializer.SDK_BROADTCAST_ACTION_STRING_PERMISSION_CHECK_ERROR); // 只要这两个广播一发出来,那你这个接收者呢就能接收到 // 注册接收者 registerReceiver(receiver, filter);// 接收一个广播接收者BroadcastReceiver,IntentFilter. } // Ctrl+I格式化 // 这是百度地图规定的,它mMapView也有生命周期方法,你必须在Activity相应的生命周期方法里面呢去调mMapView对应的生命周期方法. // 这个就没什么好记的了,死记硬背就行了.照着调用. @Override protected void onDestroy() { super.onDestroy(); // 在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理 //mMapView.onDestroy(); // 解除注册接收者 unregisterReceiver(receiver);//解除注册还是放回来. }
showToast这个方法是在Base里面,我们写到了Base里面来了.但是DemoListActivity继承了ListActivity,这里你就不能继承Base了,那你就用不到那个showToast方法.所以这时候应该把showToast一整个搬过去DemoListActivity.其实你一整个搬过去也没什么问题.但是我们最好不要那么做,一整个搬过去代码就重复了.我们最好再进行一个抽取.
这个方法叫做先使用后创建.大家可以去记一下.对于你们以后的真实开发还是很有帮助的,可以加快你们的开发速度.
package com.itheima.baidumap74.util; import android.content.Context; import android.view.Gravity; import android.widget.Toast; public class Utils { /** * 在屏幕中央显示一个Toast * @param text */ //public static void showToast(BaseActivity baseActivity, CharSequence text) { public static void showToast(Context context, CharSequence text) {//这个我们可以更加通用一点叫Context就行了,然后把之前的代码粘贴过来就行了. // TODO Auto-generated method stub Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);//局部变量toast toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); } }
package com.itheima.baidumap74; import com.baidu.mapapi.map.BaiduMap; import com.baidu.mapapi.map.MapStatusUpdate; import com.baidu.mapapi.map.MapStatusUpdateFactory; import com.baidu.mapapi.map.MapView; import com.baidu.mapapi.map.UiSettings; import com.baidu.mapapi.model.LatLng; import com.itheima.baidumap74.util.Utils; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.Gravity; import android.widget.Toast; public abstract class BaseActivity extends Activity{ // 常量要放在最前面. private static final String TAG = "BaseActivity";//TAG一般以它类名. /** 黑马坐标(北京市海淀区东北旺南路45号) */ protected LatLng hmPos = new LatLng(40.050513, 116.30361);// LatLng的一个常量表示. /** 传智坐标 */ protected LatLng czPos = new LatLng(40.065817, 116.349902); /** 天安门坐标 */ protected LatLng tamPos = new LatLng(39.915112, 116.403963); //private MapView mMapView;// protected MapView mMapView;//改一下修饰符,让子类HelloBaiduMapActivity.java可以访问. //private BaiduMap baiduMap; protected BaiduMap baiduMap;//改一下修饰符,让子类HelloBaiduMapActivity.java可以访问. // 这里加final是为了不让子类覆盖,原因是为了预防这里的一些类还没初始化的时候就被子类调用. @Override //protected void onCreate(Bundle savedInstanceState) { protected final void onCreate(Bundle savedInstanceState) {//加final,不让子类HelloBaiduMapActivity.java覆盖onCreate方法. // TODO Auto-generated method stub super.onCreate(savedInstanceState); // 在使用SDK各组件之前初始化context信息,传入ApplicationContext // 注意该方法要再setContentView方法之前实现 // SDKInitializer.initialize(getApplicationContext()); setContentView(R.layout.activity_main); // 获取地图控件引用 mMapView = (MapView) findViewById(R.id.bmapView);// MapView用于显示 // 获取地图控制器 baiduMap = mMapView.getMap();// BaiduMap地图控制器用于控制 // 这个很明显就是一个MVC模式,你这个地图显示出来之后呢我想改变显示的形状.比如说我想让地图旋转或者说是让地图放大. // 就是通过这个控制器来实现.这个是一个标准的MVC模式了. // 1. 隐藏缩放按钮、比例尺 // mMapView.showScaleControl(false);//显示比例控件 隐藏比例按钮 // 默认是显示比例按钮的.Scale是规模,比例,刻度 // mMapView.showZoomControls(false);//隐藏缩放按钮,默认是显示缩放按钮的. // 2. 获取获取最小(3)、最大缩放级别(20) float maxZoomLevel = baiduMap.getMaxZoomLevel();// 获取地图最大缩放级别 用本地/局部变量保存 float minZoomLevel = baiduMap.getMinZoomLevel();// 获取地图最小缩放级别 Log.i(TAG, "minZoomLevel = " + minZoomLevel + ", maxZoomLevel" + maxZoomLevel); // 3. 设置地图中心点为黑马 // MapStatusUpdate mapStatusUpdate = new // HelloBaiduMapActivity();//MapStatusUpdate是没有构造方法的,所以你Alt+/ new不出来. MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory .newLatLng(hmPos); baiduMap.setMapStatus(mapStatusUpdate);// setMapStatus是baiduMap地图控制器的方法.把这个状态传给我这个baiduMap.那我立马就能给你跳到这个位置. // 4.设置地图缩放为15 mapStatusUpdate = MapStatusUpdateFactory.zoomTo(15);// 不new一个经纬度的状态,是new一个缩放的状态.zoomTo是缩放一个绝对值.重复调用zoomTo()它还是缩放到那个数值. baiduMap.setMapStatus(mapStatusUpdate); // 6.获取地图Ui控制器:隐藏指南针 第六步写到base里面去 //UiSettings uiSettings = baiduMap.getUiSettings(); //uiSettings.setCompassEnabled(false); // 不显示指南针 init(); } /** 这个方法让子类实现 */ public abstract void init(); /** * 在屏幕中央显示一个Toast * @param text */ public void showToast(CharSequence text){//字符序列.字符序列这个接口 //CharSequence其实是我们String的父类.String是实现了这个接口的. //所以说我们最好面向接口来编程.这样子这个方法更加通用. //Toast toast = Toast.makeText(this, text, Toast.LENGTH_SHORT);//局部变量toast //toast.setGravity(Gravity.CENTER, 0, 0); //toast.show(); Utils.showToast(this,text);//当前这个工具类Utils不存在.BaseActivity用的是Utils这样就避免了重复. } @Override protected void onDestroy() { super.onDestroy(); // 在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理 mMapView.onDestroy(); // 解除注册接收者 //unregisterReceiver(receiver); } @Override protected void onResume() { super.onResume(); // 在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理 mMapView.onResume(); } @Override protected void onPause() { super.onPause(); // 在activity执行onPause时执行mMapView. onPause (),实现地图生命周期管理 mMapView.onPause(); } }
package com.itheima.baidumap74; //import com.itheima.baidumap74.DemoListActivity.ClassAndName; import com.baidu.mapapi.SDKInitializer; import com.itheima.baidumap74.util.Utils; import android.app.ListActivity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.view.View; import android.widget.ArrayAdapter; //import android.widget.ListAdapter; import android.widget.ListView; public class DemoListActivity extends ListActivity { private BroadcastReceiver receiver; private ClassAndName[] datas = { //把它变成成员变量.直接用静态数组,静态初始化.不用new了,直接在大括号写值就可以了. new ClassAndName(HelloBaiduMapActivity.class, "HelloBaiduMap"),//让HelloBaiduMapActivity显示到DemoListActivity里面去.把字节码HelloBaiduMapActivity.class放进来.给它起一个名字叫做HelloBaiduMap. //它就相当于一个最基础的HelloWorld的这样的一个代码. //数组的元素是ClassAndName这样的一个类型,所以要new这样一个对象作为它的元素. };//这个数组呢我们把它放到adapter的datas里面来,那这个adapter呢最终就能把你这个数组呢给你填充进去,显示到我们listview里面去. @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); registerSDKCheckReceiver(); ArrayAdapter<ClassAndName> adapter = new ArrayAdapter<DemoListActivity.ClassAndName>(this, android.R.layout.simple_list_item_1, datas);//上下文context,布局资源resource, //我们这里面的布局其实非常简单.就一个textview.所以我们这里面可以用系统里面的一个布局.系统里面给我们提供了很多简单的布局.objects其实是我们的数据.把objects改成datas吧. //适配器拿出来.ArrayAdapter它也是ListAdapter的一个子类.用ArrayAdapter,用它的真实类型. //ArrayAdapter需要接收一个数据类型T.T是一个泛型.也就是说一会儿我在适配器里面装什么你就通过泛型给我指定一下.现在我们装的是一个String. //然后你点击的时候它能跳转到这个Activity.说明我点击的时候能拿到对应的一个class.你要开启一个Activity你就要new一个intent,intent里面要传一个class. //所以我们这个对象其实包含了两个数据:一个是这个类的名字,一个是它的一个class字节码. //我们这里就按照面向对象的思想来设计. //listview要想显示数据,必须要给它一个适配器. setListAdapter(adapter);//这个方法它已经给你封装好了.它能直接设置说明它里面已经有一个listview了. } //这个就很简单,你不用去注册什么监听器了.直接覆盖它的onListItemClick方法. //跟我们注册的那个方法可以说是一模一样. @Override protected void onListItemClick(ListView l, View v, int position, long id) { // TODO Auto-generated method stub //super.onListItemClick(l, v, position, id);//super是空实现,可以删除掉. //取出单击位置的对象 ClassAndName 取出之后你就能拿到这个字节码,让它跳转到这个字节码对应的Activity. //Object itemAtPosition = l.getItemAtPosition(position);//l就是listview.把position放进来. ClassAndName classAndName = (ClassAndName) l.getItemAtPosition(position);//其实它拿出来的是ClassAndName //startActivity(new Intent(this, classAndName.cls));//开启一个Activity.上下文传this.字节码从classAndName这里面去取就行了. startActivity(new Intent(this, classAndName.clazz)); } class ClassAndName{//这个对象就封装了这个class和这个名字.数据这里就已经有了.这里我们就用它,待会Adapter里面就装它. //public ClassAndName(Class<?> cls, String name) { public ClassAndName(Class<?> clazz, String name) { super(); //this.cls = cls; this.clazz = clazz; this.name = name; } //这里面就两个内容:一个是名字, //public Class<?> cls; //名字是String,或者是写字节码也行.用泛型的话可以加一个问号.因为你不知道这一个字节码是哪一个Activity的.简写是cls. /*用于保存Activity的字节码*/ public Class<?> clazz; /*用于保存Activity对应的名字*/ public String name;//name是可以对这个类class起一个名字.这个名字你可以起一个中文名. @Override public String toString() {//打印ClassAndName的时候它就会调这个方法取这个字符串去显示. // TODO Auto-generated method stub return name; } }//Alt+Shift+S生成构造方法. @SuppressWarnings("unused") private void registerSDKCheckReceiver() { // 如果你不注册这个广播假设你这个key错了你也不知道.你可能会认为哪一步错了然后找很久找不到原因.所以我们最好去注册一下这样的一个广播. receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub // 如果说接收到广播就会跑到这里面来. // 这里面由于我们是有两个action,我们要进行一个判断,先把它们取出来. String action = intent.getAction(); if (SDKInitializer.SDK_BROADCAST_ACTION_STRING_NETWORK_ERROR .equals(action)) {// 首先是这个网络错误,. // 显示吐司这种代码很常用,如果说我们有一个base的话呢以后我们显示吐司会非常方便. // 这个base类大家应该不陌生. // 当我们接收到这一个网络处理故障的广播的时候呢, //showToast("网络错误"); //Utils.showToast(this,"网络错误");//不能用this,这里this是BroadcastReceiver Utils.showToast(DemoListActivity.this,"网络错误"); } else if (SDKInitializer.SDK_BROADTCAST_ACTION_STRING_PERMISSION_CHECK_ERROR .equals(action)) { //showToast("key验证失败"); //Utils.showToast(this,"key验证失败");//不能用this,这里this是BroadcastReceiver Utils.showToast(DemoListActivity.this,"key验证失败"); } } // 因为代码不会很多我就直接new它的内部类了. }; IntentFilter filter = new IntentFilter();// 本地变量,局部变量.IntentFilter是比较关键,也就是说你要拦截哪些广播就通过它来指定. // 监听网络错误 filter.addAction(SDKInitializer.SDK_BROADCAST_ACTION_STRING_NETWORK_ERROR);// 广播会以action的方式发出来.这个action从哪里来呢? // 我们最主要的还不是监听网络错误,我们需要的是权限检查的错误 // 监听百度地图sdk 的key是否正确. filter.addAction(SDKInitializer.SDK_BROADTCAST_ACTION_STRING_PERMISSION_CHECK_ERROR); // 只要这两个广播一发出来,那你这个接收者呢就能接收到 // 注册接收者 registerReceiver(receiver, filter);// 接收一个广播接收者BroadcastReceiver,IntentFilter. } // Ctrl+I格式化 // 这是百度地图规定的,它mMapView也有生命周期方法,你必须在Activity相应的生命周期方法里面呢去调mMapView对应的生命周期方法. // 这个就没什么好记的了,死记硬背就行了.照着调用. @Override protected void onDestroy() { super.onDestroy(); // 在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理 //mMapView.onDestroy(); // 解除注册接收者 unregisterReceiver(receiver);//解除注册还是放回来. } }
package com.itheima.baidumap74; //Ctrl+Shift+O清除多余的包名. //import com.baidu.mapapi.SDKInitializer; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; import com.baidu.mapapi.SDKInitializer; //import com.baidu.mapapi.map.BaiduMap; import com.baidu.mapapi.map.MapStatus; import com.baidu.mapapi.map.MapStatusUpdate; import com.baidu.mapapi.map.MapStatusUpdateFactory; //import com.baidu.mapapi.map.MapView; //import com.baidu.mapapi.model.LatLng; public class HelloBaiduMapActivity extends BaseActivity { //初始化方法一般放到最前面来. @Override public void init() { // TODO Auto-generated method stub //registerSDKCheckReceiver(); //baiduMap.addHeatMap(null); } // 常量要放在最前面. private static final String TAG = "HelloBaiduMapActivity";// 这个常量我们一般用它的类名就行了. /** 黑马坐标(北京市海淀区东北旺南路45号) */ //protected LatLng hmPos = new LatLng(40.050513, 116.30361);// LatLng的一个常量表示. /** 传智坐标 */ //protected LatLng czPos = new LatLng(40.065817, 116.349902); /** 天安门坐标 */ //protected LatLng tamPos = new LatLng(39.915112, 116.403963); //private MapView mMapView; //private BroadcastReceiver receiver;// 把receiver由局部/本地变量变成成员变量 //private BaiduMap baiduMap; /*@Override protected void onCreate(Bundle savedInstanceState) {//父类BaseActivity.java不给覆盖onCreate()那HelloBaiduMapActivity的初始化代码写哪里去呢? baiduMap.addHeatMap(null);//baiduMap这时候还没有初始化,所以会出现空指针异常.为了预防baiduMap在初始化之前调用, super.onCreate(savedInstanceState);//baiduMap是在父类的onCreate方法里面初始化的. registerSDKCheckReceiver(); /* * // 在使用SDK各组件之前初始化context信息,传入ApplicationContext // * 注意该方法要再setContentView方法之前实现 // * SDKInitializer.initialize(getApplicationContext()); * setContentView(R.layout.activity_main); // 获取地图控件引用 mMapView = * (MapView) findViewById(R.id.bmapView);// MapView用于显示 // 获取地图控制器 * baiduMap = mMapView.getMap();// BaiduMap地图控制器用于控制 // * 这个很明显就是一个MVC模式,你这个地图显示出来之后呢我想改变显示的形状.比如说我想让地图旋转或者说是让地图放大. // * 就是通过这个控制器来实现.这个是一个标准的MVC模式了. // 1. 隐藏缩放按钮、比例尺 // * mMapView.showScaleControl(false);//显示比例控件 隐藏比例按钮 // * 默认是显示比例按钮的.Scale是规模,比例,刻度 // * mMapView.showZoomControls(false);//隐藏缩放按钮,默认是显示缩放按钮的. * * // 2. 获取获取最小(3)、最大缩放级别(20) float maxZoomLevel = * baiduMap.getMaxZoomLevel();// 获取地图最大缩放级别 用本地/局部变量保存 float * minZoomLevel = baiduMap.getMinZoomLevel();// 获取地图最小缩放级别 Log.i(TAG, * "minZoomLevel = " + minZoomLevel + ", maxZoomLevel" + maxZoomLevel); * * // 3. 设置地图中心点为黑马 // MapStatusUpdate mapStatusUpdate = new // * HelloBaiduMapActivity();//MapStatusUpdate是没有构造方法的,所以你Alt+/ new不出来. * MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory * .newLatLng(hmPos); baiduMap.setMapStatus(mapStatusUpdate);// * setMapStatus是baiduMap地图控制器的方法.把这个状态传给我这个baiduMap.那我立马就能给你跳到这个位置. // * 4.设置地图缩放为15 mapStatusUpdate = MapStatusUpdateFactory.zoomTo(15);// * 不new一个经纬度的状态,是new一个缩放的状态.zoomTo是缩放一个绝对值.重复调用zoomTo()它还是缩放到那个数值. * baiduMap.setMapStatus(mapStatusUpdate); }*/ // 6.获取地图Ui控制器:隐藏指南针 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // TODO Auto-generated method stub MapStatusUpdate mapStatusUpdate = null;// 在最前面声明一个状态,然后默认值给它一个null switch (keyCode) { // 5.更新地图状态 case KeyEvent.KEYCODE_1: // 1)缩小 mapStatusUpdate = MapStatusUpdateFactory.zoomOut(); break; case KeyEvent.KEYCODE_2: // 2)放大 mapStatusUpdate = MapStatusUpdateFactory.zoomIn(); break; case KeyEvent.KEYCODE_3: // 3)旋转(0 ~ 360),每次在原来的基础上再旋转30度 MapStatus currentMapStatus = baiduMap.getMapStatus(); // 获取地图当前的状态. float rotate = currentMapStatus.rotate + 30;// 拿出它原来的旋转角度. Log.i(TAG, "rotate = " + rotate);// 打印旋转角度 MapStatus mapStatus = new MapStatus.Builder().rotate(rotate) .build();// MapStatus不能直接new它因为它没有构造方法,你要new的是它MapStatus.Builder的那个类.最后再 // 调用build()就能返回地图的一个状态.但是返回之前需要设置一下旋转角度.rotate()设置旋转角度. mapStatusUpdate = MapStatusUpdateFactory.newMapStatus(mapStatus); break; case KeyEvent.KEYCODE_4: // 4)俯仰(0 ~ -45),每次在原来的基础上再俯仰-5度 currentMapStatus = baiduMap.getMapStatus();// 获取地图当前的状态. float overlook = currentMapStatus.overlook - 5;// 为什么要俯仰负5度?后面演示的时候再说.因为我们拿出来是45,再减5就变成50了.所以是这个地方误导了一下,误导了.其实俯仰角度最大是负45.为什么要减5? // 因为它这个只支持负数,你给它一个正数它是看不到俯仰效果的. Log.i(TAG, "overlook = " + overlook);// 打印俯仰角度 mapStatus = new MapStatus.Builder().overlook(overlook).build();// MapStatus没有构造方法你只能重新去new它的Builder().然后调一下build()方法它就创建出来这个状态对象. // build()之前要进行一个俯仰.overlook()设置俯仰角度. mapStatusUpdate = MapStatusUpdateFactory.newMapStatus(mapStatus); break; case KeyEvent.KEYCODE_5: // 5)移动 mapStatusUpdate = MapStatusUpdateFactory.newLatLng(czPos);// 移动,它是没有move这种方法的.移动的实现是你给它一个位置(经纬度)就行了. // 移动这个状态呢它是瞬间改变你看不到效果. baiduMap.animateMapStatus(mapStatusUpdate, 2000);// animateMapStatus是能看到过程的,以动画的形式改变这个状态.2000ms,让它两秒钟完成. return super.onKeyDown(keyCode, event);// 一return这个语句就完了它就不会走下面. } baiduMap.setMapStatus(mapStatusUpdate);// 这是瞬间改变看不到过程. return super.onKeyDown(keyCode, event); } /* @SuppressWarnings("unused") private void registerSDKCheckReceiver() { // 如果你不注册这个广播假设你这个key错了你也不知道.你可能会认为哪一步错了然后找很久找不到原因.所以我们最好去注册一下这样的一个广播. receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub // 如果说接收到广播就会跑到这里面来. // 这里面由于我们是有两个action,我们要进行一个判断,先把它们取出来. String action = intent.getAction(); if (SDKInitializer.SDK_BROADCAST_ACTION_STRING_NETWORK_ERROR .equals(action)) {// 首先是这个网络错误,. // 显示吐司这种代码很常用,如果说我们有一个base的话呢以后我们显示吐司会非常方便. // 这个base类大家应该不陌生. // 当我们接收到这一个网络处理故障的广播的时候呢, showToast("网络错误"); } else if (SDKInitializer.SDK_BROADTCAST_ACTION_STRING_PERMISSION_CHECK_ERROR .equals(action)) { showToast("key验证失败"); } } // 因为代码不会很多我就直接new它的内部类了. }; IntentFilter filter = new IntentFilter();// 本地变量,局部变量.IntentFilter是比较关键,也就是说你要拦截哪些广播就通过它来指定. // 监听网络错误 filter.addAction(SDKInitializer.SDK_BROADCAST_ACTION_STRING_NETWORK_ERROR);// 广播会以action的方式发出来.这个action从哪里来呢? // 我们最主要的还不是监听网络错误,我们需要的是权限检查的错误 // 监听百度地图sdk 的key是否正确. filter.addAction(SDKInitializer.SDK_BROADTCAST_ACTION_STRING_PERMISSION_CHECK_ERROR); // 只要这两个广播一发出来,那你这个接收者呢就能接收到 // 注册接收者 registerReceiver(receiver, filter);// 接收一个广播接收者BroadcastReceiver,IntentFilter. } // Ctrl+I格式化 // 这是百度地图规定的,它mMapView也有生命周期方法,你必须在Activity相应的生命周期方法里面呢去调mMapView对应的生命周期方法. // 这个就没什么好记的了,死记硬背就行了.照着调用. @Override protected void onDestroy() { super.onDestroy(); // 在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理 //mMapView.onDestroy(); // 解除注册接收者 unregisterReceiver(receiver);//解除注册还是放回来. } */ /* @Override protected void onResume() { super.onResume(); // 在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理 mMapView.onResume(); } @Override protected void onPause() { super.onPause(); // 在activity执行onPause时执行mMapView. onPause (),实现地图生命周期管理 mMapView.onPause(); } */ }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.itheima.baidumap74" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.GET_TASKS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <!-- 增加读电话状态的权限.这个你不加也无所谓,但是看到报那个黄色异常还是挺不爽的.还是把它加一下. --> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <application android:name=".MyApplication" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <!-- .就代表你前面这个基础的一个包 --> <meta-data android:name="com.baidu.lbsapi.API_KEY" android:value="QaDs6ScFuwxGh75ku6gijqNnBhnXmNqZ" /> <!-- 下面这个activity也是一样,简单一点,以.打头就行了.这样看起来会比较简短一点,看起来会比较舒服. android:name="com.itheima.baidumap74.MainActivity" --> <!-- 把 DemoListActivity配置成第一个启动类.--> <activity android:name=".DemoListActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- HelloBaiduMapActivity就简短一点. --> <activity android:name=".HelloBaiduMapActivity" /> </application> </manifest>