每一台电脑都要申请属于自己的android:apiKey,要是使用别人的android:apiKey,
则地图只显示方格,不会有实际的地图出现,并且在Android虚拟机重建或者重装电脑的操作系统的时候
也要重新申请android:apiKey,关于如何申请,我在“申请Google Map服务”中已说得很详细。
新建一个地图项目。
在main.xml中:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.google.android.maps.MapView
android:id="@+id/mapview"
android:clickable="true" android:enabled="true"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:apiKey="0Pm9QrsSh_mwtc6rMyqZMRu71qFpIB51UXVWHmg" />
</LinearLayout>
在MyOverlayImpl.java中:
package com.li.googlemapproject;
import java.util.ArrayList;
import java.util.List;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.drawable.Drawable;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.OverlayItem;
public class MyOverlayImpl extends ItemizedOverlay<OverlayItem> {
private List<OverlayItem> allOverlayItems = new ArrayList<OverlayItem>();
private Context context = null;
public MyOverlayImpl(Drawable defaultMarker, Context context) {
super(boundCenter(defaultMarker));
this.context = context;
}
@Override
protected OverlayItem createItem(int i) {
return this.allOverlayItems.get(i);
}
@Override
public int size() {
return this.allOverlayItems.size();
}
@Override
protected boolean onTap(int index) { // 单击标记图片之后的操作
OverlayItem item = this.allOverlayItems.get(index); // 取得指定的点
Dialog dialog = new AlertDialog.Builder(this.context)
.setIcon(R.drawable.pic_m).setTitle(item.getTitle())
.setMessage(item.getSnippet())
.setPositiveButton("关闭", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
}).create();
dialog.show();
return true;
}
public void addOverlayItem(OverlayItem item) {
this.allOverlayItems.add(item);
super.populate();
}
}
在PaintLineOverlay.java中:
package com.li.googlemapproject;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Point;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;
public class PaintLineOverlay extends Overlay {
private GeoPoint beginGeoPoint = null;
private GeoPoint endGeoPoint = null;
public PaintLineOverlay(GeoPoint beginGeoPoint, GeoPoint endGeoPoint) {
this.beginGeoPoint = beginGeoPoint;
this.endGeoPoint = endGeoPoint;
}
@Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
Paint paint = new Paint();
paint.setStyle(Style.FILL_AND_STROKE);
paint.setStrokeWidth(3);
paint.setColor(Color.RED);
Point beginPoint = new Point();
Point endPoint = new Point();
Projection projection = mapView.getProjection();
projection.toPixels(this.beginGeoPoint, beginPoint);
projection.toPixels(this.endGeoPoint, endPoint);
canvas.drawLine(beginPoint.x, beginPoint.y, endPoint.x, endPoint.y,
paint);
}
}
在PaintPointOverlay.java中:
package com.li.googlemapproject;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;
public class PaintPointOverlay extends Overlay {
private GeoPoint geoPoint = null;
public PaintPointOverlay(GeoPoint geoPoint) {
this.geoPoint = geoPoint;
}
@Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
Point point = new Point();
Projection projection = mapView.getProjection();
projection.toPixels(this.geoPoint, point); // 将地图上坐标的点设置为绘图屏幕的点
Paint paint = new Paint();
paint.setColor(Color.RED);
canvas.drawCircle(point.x, point.y, 6, paint);
}
}
在MyGoogleMapDemo.java中:
package com.li.googlemapproject;
import android.os.Bundle;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
public class MyGoogleMapDemo extends MapActivity {
private MapView mapView = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.main);
this.mapView = (MapView) super.findViewById(R.id.mapview); // 取得地图视图
this.mapView.setBuiltInZoomControls(true);
// 给定一个坐标:天安门的坐标:116.3975060,39.9087110
GeoPoint beginGeoPoint = new GeoPoint((int) (39.9087110 * 1E6),
(int) (116.3975060 * 1E6));
GeoPoint endGeoPoint = new GeoPoint((int) (39.9995740 * 1E6),
(int) (116.2739010 * 1E6));
this.mapView.getOverlays().add(new PaintPointOverlay(beginGeoPoint));
this.mapView.getOverlays().add(new PaintPointOverlay(endGeoPoint));
this.mapView.getOverlays().add(
new PaintLineOverlay(beginGeoPoint, endGeoPoint));
MapController mapController = this.mapView.getController() ;
mapController.animateTo(beginGeoPoint); // 设置坐标的动画
mapController.setZoom(12); // 最大的级别是12
}
@Override
protected boolean isRouteDisplayed() {
return false;
}
}
在AndroidManifest.xml中修改权限:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.li.googlemapproject"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MyGoogleMapDemo"
android:label="@string/title_activity_my_google_map_demo" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<uses-library android:name="com.google.android.maps" />
</application>
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
第一继承自UIControl
添加事件
[textField addTarget:self action:@selector(didDone:) forControlEvents:UIControlEventEditingDidEndOnExit];
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField; // return NO to disallow editing.
返回值是true或false
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
NSLog(@"textFieldShouldBeginEditing");
return YES;
}
- (void)textFieldDidBeginEdiUITextField *)textField; // became first responder
此时已变成第一响应者
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
NSLog(@"textFieldDidBeginEditing");
return YES;
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField; // return YES to allow editing to stop and to resign first responder status. NO to disallow the editing session to end
编辑完之后,键盘放弃第一响应者
- (void)textFieldDidEndEditing:(UITextField *)textField; // may be called if forced even if shouldEndEditing returns NO (e.g. view removed from window) or endEditing:YES called
输入结束之后调用
- (void)textFieldDidEndEditing:(UITextField *)textField
{
NSLog(@"textFieldDidEndEditing");
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string; // return NO to not change text
通过每次输入的内容,返回YES,则会在textField做显示,否则不显示
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSLog(@"the input char is %@",string);
return YES;
}
- (BOOL)textFieldShouldClear:(UITextField *)textField; // called when clear button pressed. return NO to ignore (no notifications)
如果返回值是NO ,则点击clear不会清除
- (BOOL)textFieldShouldClear:(UITextField *)textField
{
NSLog(@"textFieldShouldClear");
return NO;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField; // called when 'return' key pressed. return NO to ignore
点击return 钮之后,是否仍然显示
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{// called when 'return' key pressed. return NO to ignore.
return NO;
}
对于这个面试题,相信大家都见过,网上给出的答案是:
1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
2、设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
3、设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法
然而,我在测试的时候,发现并不是这样,下面写了一个简单的测试类,代码如下:
Activity:
package com.home.activity; import android.os.Bundle; import android.util.Log; import android.app.Activity; import android.content.res.Configuration; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.i("onCreate", "执行onCreate方法"); } @Override protected void onStart() { super.onStart(); Log.i("onStart", "执行onStart方法"); } @Override protected void onResume() { super.onResume(); Log.i("onResume", "执行onResume方法"); } @Override protected void onPause() { super.onPause(); Log.i("onPause", "执行onPause方法"); } @Override protected void onStop() { super.onStop(); Log.i("onStop", "执行onStop方法"); } @Override protected void onDestroy() { super.onDestroy(); Log.i("onDestroy", "执行onDestroy方法"); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); Log.i("onConfigurationChanged", "执行onConfigurationChanged方法"); } @Override protected void onRestart() { super.onRestart(); Log.i("onRestart", "执行onRestart方法"); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); Log.i("onSaveInstanceState", "执行onSaveInstanceState方法"); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); Log.i("onRestoreInstanceState", "执行onRestoreInstanceState方法"); } }
下面来分析打印结果:
我分别用手机和模拟器进行测试过,发现它们有点区别:
1、不设置Activity的android:configChanges时,手机和模拟器打印的结果都一样:横竖屏切换都执行一次生命周期
2、设置Activity的android:configChanges="orientation"时,模拟器打印的结果和上面一样,横竖屏切换都执行一次生命周期:
以示区别,我将onCreate打印成红色
可以看出和上面结果一样。但是在手机上测试就不同了,它只会打印一句话:
3、设置Activity的android:configChanges="orientation|keyboardHidden"时,手机和模拟器的结果一样:
那么,综上所述:
结论应该是这样:
1、不设置Activity的android:configChanges时,横竖屏切换都执行一次生命周期。
2、设置Activity的android:configChanges="orientation"时,模拟器上横竖屏切换都执行一次生命周期。手机上只执行
onConfigurationChanged方法。
3、设置Activity的android:configChanges="orientation|keyboardHidden"时,无论在模拟器还是手机上,横竖屏切换都只执行onConfigurationChanged方法。
上面测试模拟器用的2.3.3,手机用2.3和4.1.2都测试过。
大家有兴趣可以用不同版本的手机进行测试下,也许有不同的结果,若留言告知我,在下不胜感激。