最近自己在弄一个跟地图相关的android应用,想在地图中间增加一个十字架,在按下地位按钮时,地图上的点能与十字架对准。
在网上搜索了一下,这方面的文章比较少,有一篇文章《自定义十字架》(链接http://blog.csdn.net/bzy601638015/article/details/38800365),我试着按这位博主的文章去做,发现十字架与定位点有偏差。
后来发现是因为标题栏的高度,因为计算时,只是得到了状态栏的高度。参照《自定义十字架》这篇文章,再结合自己的实际应用,进行了修改。
1、先在res/values 目录下自定义一个View 的xml文件,名字为view_cross.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CrossView">
<attr name="lineWidth" format="dimension"></attr>
<attr name="lineLength" format="dimension"></attr>
<attr name="lineColor" format="color"></attr>
</declare-styleable>
</resources>
其中,lineWidth 为线宽,lineLength为线长,lineColor为线的颜色。
2.在src的包下,建立一个名为CrossView的java文件
public class CrossView extends View{
private int mLength;
private int mWidth;
private int mColor;
private Context mContext;
private Paint mPaint;
public CrossView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public CrossView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// TODO Auto-generated constructor stub
}
public CrossView(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext= context;
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CrossView);
mLength = (int) ta.getDimension(R.styleable.CrossView_lineLength, 20);
mWidth = (int) ta.getDimension(R.styleable.CrossView_lineWidth, 0);
mColor = ta.getColor(R.styleable.CrossView_lineColor, 0);
mPaint = new Paint();
mPaint.setColor(mColor);
mPaint.setStrokeWidth(mWidth);
mPaint.setAntiAlias(true);
ta.recycle();
}
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
DrawCrossView(canvas);
}
private void DrawCrossView(Canvas canvas) {
// 获取屏幕的尺寸
DisplayMetrics dm = getResources().getDisplayMetrics();
int width = dm.widthPixels;
int height = dm.heightPixels;
// 获取状态栏的高度
Rect frame = new Rect();
getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
// 设置竖线的位置
int startX = width / 2;
int startY = height / 2 - statusBarHeight/2 - mLength / 2;
int stopX = startX;
int stopY = startY + mLength;
Log.i("ScreenHeight", height + "");
Log.i("ScreenWidth", width + "");
Log.i("statusBarHeight", statusBarHeight + "");
Log.i("startY", startY + "");
Log.i("stopY", stopY + "");
Log.i("mLength", mLength/2 + "");
canvas.drawLine(startX, startY, stopX, stopY, mPaint);
// 设置横线的位置
startX = width / 2 - mLength / 2;
startY = (height - statusBarHeight) / 2;
stopX = startX + mLength;
stopY = startY;
Log.d("startX", startX + "");
canvas.drawLine(startX, startY, stopX, stopY, mPaint);
}
}
其中,自定义View需要用到TypeArray,相关资料可参考《android自定义属性atts.xml, TypeArray学习》(链接http://blog.csdn.net/lilu_leo/article/details/7449973)
mWidth = (int) ta.getDimension(R.styleable.CrossView_lineWidth, 0);
mColor = ta.getColor(R.styleable.CrossView_lineColor, 0);
上下面的两个参数最后一位可以为0.
3、在地图界面加入CrossView
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:yxh="http://schemas.android.com/apk/res/com.yxh.googlemap"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.yxh.googlemap.MainActivity" >
<fragment
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.MapFragment" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/displayProjectName"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:lines="1"
android:maxLength="10"
android:text="@string/displayProjectName"
android:textSize="8pt" />
<Button
android:id="@+id/NormalMapButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="NormolView"
android:text="@string/NromoMapButton" />
<Button
android:id="@+id/SatelliteMapButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="Satellite"
android:text="@string/SatelliteMapButton" />
</LinearLayout>
<Button
android:id="@+id/addMarker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:text="@string/addMarker" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<com.yxh.googlemap.CrossView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
yxh:lineWidth="2dp"
yxh:lineColor="#000000"/>
</LinearLayout>
</FrameLayout>
在地图界面中用一个LinearLayout包裹我们的CrossView.这里,我把线宽定位2dp, 线的颜色为黑色。
最后运行,发现有问题。如上图所示,十字架与定位点出现偏差。弄了好久才发现在《自定义十字架》的这篇文章中,没有标题栏的高度,所以,而我这里有标题栏。这才是出现偏差的原因。后来,我也在网上找了好多关于求标题栏高度的,用getWindow()的方式,但是,都不行。当然,如果哪位朋友可有解决方案的,希望能告诉我。
后来,我就觉得不要标题栏。就在AndroidManifest.xml中地图的Activity加入android:theme = "@android:style/Theme.NoTitleBar"
<!-- 启动地图界面 -->
<activity
android:name=".MapFragmentActivity"
android:theme="@android:style/Theme.NoTitleBar">
</activity>
最后,十字架终于和定位点重合在一起了。