1. 程式人生 > >android自定義view之地圖(一)

android自定義view之地圖(一)

最近參加了一個比賽,要用到自己做一個自定義的小地圖,所以在網上查找了一些關於自定義view的有關資料,也瞭解了自定義控制元件的初步知識。

效果圖

第一階段的效果圖
第一階段我畫了一個自制的網格圖,點哪個網格就會哪個網格就會顯示。

工作環境圖

這裡寫圖片描述

程式碼介紹

1。我們都知道當使用android的原始控制元件時,每個控制元件都可以定義屬性,比如android:id ,android:layout_width等等大家並不陌生的屬性,有些屬性是每個控制元件都有的比如上面兩個,還有一些是控制元件自己有的。我們自定義的控制元件可以定義自己想要的屬性,方便我們以後自己使用。

那就是在values目錄下建立一個attrs.xml檔案。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MapView">
        <attr name="border_color" format="color" />
        <attr name="border_width" format="dimension" />
    </declare-styleable>
</resources>

這樣就給我們的我們就給控制元件加了 border_color 和border_width 兩個屬性,在這裡的format裡定義的是我們的屬性的值是什麼型別,比如border_color是color,border_width是dimension,每個不同的資料型別對應不同的型別。

2.第二部分也是最重要的自定義控制元件的類。

首先我們的自定義類要繼承View

public class CustomView extends View {
}

接下來我們完成view要實現的三個不同引數的建構函式,其中init是我們自己寫的初始化資訊的函式。在第二個建構函式中,我們獲取了我們在attrs.xml中定義的值。

public CustomView(Context context) {
        super(context);
        //初始化資訊
        init();
}

public CustomView(Context context, AttributeSet attrs) {
        super
(context, attrs); //獲取我們自己的屬性 TypedArray typedArray = context.getTheme().obtainStyledAttributes( attrs, R.styleable.MapView, 0, 0); try { mBorderColor = typedArray.getColor( R.styleable.MapView_border_color, 0xff000000); mBorderWidth = typedArray.getDimension( R.styleable.MapView_border_width, 2); } finally { typedArray.recycle(); } init(); } public CustomView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); }

然後是覆些view中這幾個函式
onSizeChanged(int w, int h, int oldw, int oldh) {}這個函式是獲取我們view的設定的大小
onDraw(Canvas canvas){}是設定view中的繪畫,也是view中最重要的函式
onTouchEvent(MotionEvent event){}是設定點選事件

package com.example.myview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class CustomView extends View {

    private float mBorderWidth;
    private int mBorderColor;
    private Paint mPaint;
    private RectF mBounds;
    private float width;
    private float height;
    float radius;
    // 格子的數量
    private int boxnum = 50;
    // 每個方塊的長度
    float lenOfWidth;
    float lenOfHeight;

    PointF pointF;

    public CustomView(Context context) {
        super(context);
        init();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        MyPoint point = getMyPoint(event.getX(), event.getY());
        if (point == null)
            return false;
        pointF = getPointF(point.getX(), point.getY());

        invalidate();
        return true;
    }

    // 把xy的座標轉換我座標
    public MyPoint getMyPoint(float eventX, float eventY) {
        // 注意觸碰的x,y座標軸與計算機的陣列相反- -
        int y = (int) ((eventX - (mBounds.centerX() - (float) 0.9 * width / 2)) / lenOfWidth);
        int x = (int) ((eventY - (mBounds.centerY() - (float) 0.9 * height / 2)) / lenOfHeight);
        if (x < 0 || x >= boxnum || y < 0 || y >= boxnum)
            return null;
        return new MyPoint(x, y);
    }

    // 把座標轉換成螢幕座標
    public PointF getPointF(int x, int y) {
        // 注意觸碰的x,y座標軸與計算機的陣列相反- -
        float temp_x = y * lenOfWidth
                + (mBounds.centerX() - (float) 0.9 * width / 2);
        float temp_y = x * lenOfHeight
                + (mBounds.centerY() - (float) 0.9 * height / 2);
        PointF pointF = new PointF(temp_x, temp_y);
        return pointF;
    }

    public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray typedArray = context.getTheme().obtainStyledAttributes(
                attrs, R.styleable.MapView, 0, 0);

        try {
            mBorderColor = typedArray.getColor(
                    R.styleable.MapView_border_color, 0xff000000);
            mBorderWidth = typedArray.getDimension(
                    R.styleable.MapView_border_width, 2);
        } finally {
            typedArray.recycle();
        }

        init();
    }

    public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(mBorderWidth);
        mPaint.setColor(mBorderColor);
        mPaint.setAlpha(255);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        mBounds = new RectF(getLeft(), getTop(), getRight(), getBottom());

        width = mBounds.right - mBounds.left;
        height = mBounds.bottom - mBounds.top;

        if (width < height) {
            radius = width / 4;
        } else {
            radius = height / 4;
        }
        lenOfWidth = (float) 0.9 * width / boxnum;
        lenOfHeight = (float) 0.9 * height / boxnum;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setColor(0x66555555);
        canvas.drawRoundRect(
                new RectF(mBounds.centerX() - (float) 0.9 * width / 2, mBounds
                        .centerY() - (float) 0.9 * height / 2, mBounds
                        .centerX() + (float) 0.9 * width / 2, mBounds.centerY()
                        + (float) 0.9 * height / 2), 30, 30, mPaint);

        float lenOfWidth = (float) 0.9 * width / boxnum;
        float lenOfHeight = (float) 0.9 * height / boxnum;
        // 畫豎線
        for (int i = 0; i < boxnum; i++) {
            canvas.drawLine(mBounds.centerX() - (float) 0.9 * width / 2 + i
                    * lenOfWidth, mBounds.centerY() - (float) 0.9 * height / 2,
                    mBounds.centerX() - (float) 0.9 * width / 2 + i
                            * lenOfWidth, mBounds.centerY() + (float) 0.9
                            * height / 2, mPaint);
            canvas.drawLine(mBounds.centerX() - (float) 0.9 * width / 2,
                    mBounds.centerY() - (float) 0.9 * height / 2 + i
                            * lenOfHeight, mBounds.centerX() + (float) 0.9
                            * width / 2, mBounds.centerY() - (float) 0.9
                            * height / 2 + i * lenOfHeight, mPaint);
        }

        if (pointF != null) {
            // 畫出自己在哪裡
            mPaint.setColor(Color.BLUE);
            canvas.drawRect(new RectF(pointF.x, pointF.y,
                    pointF.x + lenOfWidth, pointF.y + lenOfHeight), mPaint);
        }
    }
}

3.最後是我們acitivity檔案和xml佈局檔案

package com.example.myview;

import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity {

    private CustomView view;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        view=(CustomView) findViewById(R.id.view1);
    }

}

佈局檔案

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
<FrameLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
        <com.example.myview.CustomView

            android:id="@+id/view1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:border_color="#ff1ff41f"
            app:border_width="1dp"/>
    </FrameLayout>

</LinearLayout>