欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android自定義LocationMarker的實(shí)現(xiàn)詳解

 更新時(shí)間:2023年02月10日 14:03:24   作者:cxy107750  
這篇文章主要為大家詳細(xì)介紹一個(gè)比較簡(jiǎn)單的東西:自定義繪制Marker 其實(shí)就是自定義view, 跟軌跡沒(méi)太多關(guān)聯(lián),感興趣的小伙伴可以跟隨小編一起了解一下

今天講一個(gè)比較簡(jiǎn)單的東西自定義繪制Marker 其實(shí)就是自定義view, 跟軌跡沒(méi)太多關(guān)聯(lián),還有軌跡源碼在文末分享出來(lái),對(duì)您有幫助的話給個(gè)star唄。

如下面的gif中的軌跡中的LocationMarker

自定義View LocationMarker

主要包括繪制水滴狀,繪制圓、繪制文字,繪制底部橢圓陰影,主要是繪制水滴狀,這里用的貝塞爾三階繪制,首先直接看代碼:

public class LocationMarker extends View {
    private Path mPath;
    private Paint mFillCirclePaint;
    private Paint mTextPaint;
    private VPoint p2;
    private VPoint p4;
    private HPoint p1;
    private HPoint p3;
    private Context mContext;

    private float c;
    private float blackMagic = 0.551915024494f;
    private int wrapperColor;
    private int circleColor;

    private int radius = DisplayUtil.dip2px(20);
    private String mMilePost;
    private int textSize = 13;

    private boolean drawBottomShader;

    public LocationMarker(Context context, int radius, String milePost, int textSize) {
        this(context, null);
        this.mContext = context;
        this.radius = radius;
        this.mMilePost = milePost;
        this.textSize = textSize;
        init();
    }

    public LocationMarker(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        this.mContext = context;
        init();
    }

    public LocationMarker(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext = context;
        init();
    }

    /**
     * 初始化操作
     */
    private void init() {
        mFillCirclePaint = new Paint();
        mFillCirclePaint.setColor(0xFFFFFFFF);
        mFillCirclePaint.setStyle(Paint.Style.FILL);
        mFillCirclePaint.setStrokeWidth(1);
        mFillCirclePaint.setAntiAlias(true);
        mPath = new Path();
        p2 = new VPoint();
        p4 = new VPoint();
        p1 = new HPoint();
        p3 = new HPoint();
        c = radius * blackMagic;
        initTextPain();
        wrapperColor = R.color.location_wrapper;
        circleColor = R.color.location_inner_circle;
    }

    public void setColors(int wrapperColorResource, int circleColorResource){
        this.wrapperColor = wrapperColorResource;
        this.circleColor = circleColorResource;
    }


    private void initTextPain() {
        mTextPaint = new Paint();
        mTextPaint.setColor(0xFFFFFFFF);
        mTextPaint.setStyle(Paint.Style.FILL);
        mTextPaint.setStrokeWidth(1);
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTypeface(Typeface.DEFAULT_BOLD);
        mTextPaint.setTextSize(DisplayUtil.sp2px(mContext, textSize));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        mPath.reset();
        canvas.translate(getWidth() / 2, getHeight() / 2);
        drawWaterDrop(canvas, radius);
    }

 
    private void drawWaterDrop(Canvas canvas, int radius) {
        canvas.save();
        Path path = getPath(radius);

      //內(nèi)部圓的path
        Path circle = new Path();
        circle.addCircle(p3.x, p3.y + radius, radius - radius / 5, Path.Direction.CCW);

        //去鋸齒
        canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
        drawBottomOval(canvas);
      //繪制外部的水滴狀
        drawBezierPath(canvas, ColorUtil.getResourcesColor(mContext, wrapperColor), path);
      //繪制內(nèi)部的圓
        drawBezierPath(canvas, ColorUtil.getResourcesColor(mContext, circleColor), circle);
        drawText(canvas, mMilePost);
        canvas.restore();
    }

  	//繪制底部的陰影,drawBottomShader控制是否顯示陰影
    private void drawBottomOval(Canvas canvas){
        if (drawBottomShader){
            RectF rectF = new RectF();
            float width = DisplayUtil.dip2px(12);
            float height = DisplayUtil.dip2px(4);
            rectF.set(p1.x - width/2, p1.y - height/2, p1.x + width/2, p1.y + height/2);
            int color = mFillCirclePaint.getColor();
            mFillCirclePaint.setColor(ColorUtil.getResourcesColor(mContext, R.color.location_bottom_shader));
            canvas.drawOval(rectF, mFillCirclePaint);
            mFillCirclePaint.setColor(color);
        }
    }

  	//繪制Marker中心的文字
    private void drawText(Canvas canvas, String mileStr) {
        RectF rectF = new RectF();
        float width = mTextPaint.measureText(mileStr);

        float rectFLeft = p3.x - width / 2 ;
        float rectFRight = p3.x + width / 2 ;

        float rectHeight = TextUtil.getTxtHeight1(mTextPaint);
        float rectTop = p2.y + DisplayUtil.dip2px(2);//調(diào)整位置,看起來(lái)居中
        float rectBottom = p2.y + rectHeight;

        rectF.set(rectFLeft, rectTop, rectFRight, rectBottom);

        Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
        float top = fontMetrics.top;//為基線到字體上邊框的距離,即上圖中的top
        float bottom = fontMetrics.bottom;//為基線到字體下邊框的距離,即上圖中的bottom
        int baseLineY = (int) (rectF.centerY() + (top + bottom) / 2);//基線中間點(diǎn)的y軸計(jì)算公式
        canvas.drawText(mileStr, rectF.left, baseLineY, mTextPaint);
    }

    /**
     * 畫圓
     */
    private Path getPath(int radius) {
        CircleModel(radius);
        Path path = new Path();
        p1.setY(p1.y + radius * 0.2f * 1.05f); //設(shè)置 p1 底部左右兩個(gè)點(diǎn)的y值
        p1.y += radius * 0.2f * 1.05f;//設(shè)置 p1 自己的y值
        path.moveTo(p1.x, p1.y);
        path.cubicTo(p1.right.x, p1.right.y, p2.bottom.x, p2.bottom.y, p2.x, p2.y);
        path.cubicTo(p2.top.x, p2.top.y, p3.right.x, p3.right.y, p3.x, p3.y);
        path.cubicTo(p3.left.x, p3.left.y, p4.top.x, p4.top.y, p4.x, p4.y);
        path.cubicTo(p4.bottom.x, p4.bottom.y, p1.left.x, p1.left.y, p1.x, p1.y);
        path.close();

        return path;
    }

    private void drawBezierPath(Canvas canvas, int color, Path path) {
        int colorOrigin = mFillCirclePaint.getColor();
        mFillCirclePaint.setColor(color);
        canvas.drawPath(path, mFillCirclePaint);
        mFillCirclePaint.setColor(colorOrigin);
    }

    private void CircleModel(int radius) {
        c = radius * blackMagic;
        p1.setY(radius);//右邊
        p3.setY(-radius);// 左邊
        p3.x = p1.x = 0;//圓心

        p3.left.x = -c;
        p3.right.x = c;
        p1.left.x = -c * 0.36f;
        p1.right.x = c * 0.36f;
        //p1.p3屬于圓的上下兩點(diǎn)
        p2.setX(radius); // 下邊
        p4.setX(-radius);// 上邊
        p2.y = p4.y = 0;//  圓心
        p2.top.y = p4.top.y = -c;
        p2.bottom.y = p4.bottom.y = c;
    }


    public void setDrawBottomShader(boolean drawBottomShader) {
        this.drawBottomShader = drawBottomShader;
    }
}

簡(jiǎn)單的講一下,主要通過(guò)三階貝塞爾曲線來(lái)繪制圓,在圓的基礎(chǔ)上,對(duì)Bottom方向的P1(包含 p1本身以及l(fā)eft、right兩個(gè)control點(diǎn))拉升,類似行星跟衛(wèi)星的潮汐引力在朝下拉升的方向形成水滴形的尖角。

這里left、top、right、bottom四個(gè)方向,每個(gè)方向共三個(gè)點(diǎn),共同確定這個(gè)圓。

VPoint 代表垂直方向的 left、right,這里是 p2跟p4 分表包含三個(gè)點(diǎn),三點(diǎn)成線跟圓的左邊、右邊相切。

public class VPoint {
    public float x;
    public float y;
    public PointF top = new PointF();
    public PointF bottom = new PointF();

    public void setX(float x) {
        this.x = x;
        top.x = x;
        bottom.x = x;
    }

    public void adjustY(float offset) {
        top.y -= offset;
        bottom.y += offset;
    }

    public void adjustAllX(float offset) {
        this.x += offset;
        top.x += offset;
        bottom.x += offset;
    }

    public void adjustAllY(float offset) {
        this.y += offset;
        top.y += offset;
        bottom.y += offset;
    }

    public void adjustAllXY(float x, float y) {
        adjustAllX(x);
        adjustAllY(y);
    }
}

同樣, HPoint 代表水邊方向圓的切線,p1跟p3代表Bottom、Top上的三個(gè)點(diǎn)。

public class HPoint {
    public float x;
    public float y;
    public PointF left = new PointF();
    public PointF right = new PointF();

    public void setY(float y) {
        this.y = y;
        left.y = y;
        right.y = y;
    }

    public void adjustAllX(float offset) {
        this.x += offset;
        left.x += offset;
        right.x += offset;
    }

    public void adjustAllY(float offset) {
        this.y += offset;
        left.y += offset;
        right.y += offset;
    }

    public void adjustAllXY(float x, float y) {
        adjustAllX(x);
        adjustAllY(y);
    }
}

其它的見(jiàn)代碼注釋。

應(yīng)用自定義View到AMapView中

這里就直接參考高德的demo,需要注意一點(diǎn)的是,在加載自定義的LocationMarker時(shí),我在LocationMarker的外層包了兩層父View,試過(guò)了一層顯示不出來(lái)

private void addMarker(LatLng position, String displayStr,int radius, int textSize, int wrapperColor, int circleColor, boolean showBottomShader){
		View view = View.inflate(RecordCorrectShowActivity.this, R.layout.custom_location_view, null);
		RelativeLayout locationContainer = view.findViewById(R.id.locationContainer);
		LocationMarker locationMarker = new LocationMarker(mMapView.getContext(),
				DisplayUtil.dip2px(radius), displayStr, textSize);
		locationMarker.setColors(wrapperColor, circleColor);
		locationMarker.setDrawBottomShader(showBottomShader);

		locationContainer.addView(locationMarker);
		BitmapDescriptor markerIcon = BitmapDescriptorFactory.fromView(view);

		MarkerOptions optionPosition = new MarkerOptions()
				.position(position)
				.icon(markerIcon);
		Marker marker = mAMap.addMarker(optionPosition);

		Animation markerAnimation = new ScaleAnimation(0, 1, 0, 1); //初始化生長(zhǎng)效果動(dòng)畫
		markerAnimation.setDuration(1000);  //設(shè)置動(dòng)畫時(shí)間 單位毫秒
		marker.setAnimation(markerAnimation);

		marker.startAnimation();
	}

兩層父view的

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <RelativeLayout
        android:id="@+id/locationContainer"
        android:layout_width="50dp"
        android:layout_height="55dp"/>

</LinearLayout>

下次講優(yōu)化軌跡路徑,從采集時(shí)到最后的優(yōu)化。

代碼請(qǐng)前往 運(yùn)動(dòng)軌跡, 代碼包含了很多圖表Chart的代碼沒(méi)有分開(kāi),有空對(duì)這個(gè)庫(kù)做個(gè)系列,因?yàn)镸AAndroidChart沒(méi)法滿足需求做的庫(kù), 代碼中需要自己去高德平臺(tái)上注冊(cè)Key。

以上就是Android自定義LocationMarker的實(shí)現(xiàn)詳解的詳細(xì)內(nèi)容,更多關(guān)于Android自定義LocationMarker的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Android系統(tǒng)中的藍(lán)牙連接程序編寫實(shí)例教程

    Android系統(tǒng)中的藍(lán)牙連接程序編寫實(shí)例教程

    這篇文章主要介紹了Android系統(tǒng)中的藍(lán)牙連接程序編寫實(shí)例教程,包括藍(lán)牙的設(shè)備查找及自動(dòng)配對(duì)等各種基礎(chǔ)功能的實(shí)現(xiàn),十分給力,需要的朋友可以參考下
    2016-04-04
  • Android自定義控件實(shí)現(xiàn)底部菜單(上)

    Android自定義控件實(shí)現(xiàn)底部菜單(上)

    這篇文章主要為大家詳細(xì)介紹了Android自定義控件實(shí)現(xiàn)底部菜單的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Android 通過(guò)onDraw實(shí)現(xiàn)在View中繪圖操作的示例

    Android 通過(guò)onDraw實(shí)現(xiàn)在View中繪圖操作的示例

    以下是對(duì)Android通過(guò)onDraw實(shí)現(xiàn)在View中繪圖操作的示例代碼進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過(guò)來(lái)參考下
    2013-07-07
  • Android開(kāi)發(fā)之基本控件和四種布局方式詳解

    Android開(kāi)發(fā)之基本控件和四種布局方式詳解

    這篇文章主要介紹了Android開(kāi)發(fā)之基本控件和四種布局方式詳解的相關(guān)資料,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-06-06
  • Android中單例模式的一些坑小結(jié)

    Android中單例模式的一些坑小結(jié)

    這篇文章主要給大家介紹了關(guān)于Android中單例模式的一些坑,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02
  • Android基礎(chǔ)控件RadioGroup使用方法詳解

    Android基礎(chǔ)控件RadioGroup使用方法詳解

    這篇文章主要為大家詳細(xì)介紹了Android基礎(chǔ)控件RadioGroup的使用方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • Android使用Room數(shù)據(jù)庫(kù)解決本地持久化的操作

    Android使用Room數(shù)據(jù)庫(kù)解決本地持久化的操作

    Room 是一個(gè)持久性庫(kù),屬于 Android Jetpack 的一部分,Room 是 SQLite 數(shù)據(jù)庫(kù)之上的一個(gè)抽象層,Room 并不直接使用 SQLite,而是負(fù)責(zé)簡(jiǎn)化數(shù)據(jù)庫(kù)設(shè)置和配置以及與數(shù)據(jù)庫(kù)交互方面的瑣碎工作,本文介紹了Android使用Room數(shù)據(jù)庫(kù)解決本地持久化的操作,需要的朋友可以參考下
    2024-09-09
  • Android ListView實(shí)現(xiàn)上拉加載更多和下拉刷新功能

    Android ListView實(shí)現(xiàn)上拉加載更多和下拉刷新功能

    這篇文章主要為大家詳細(xì)介紹了Android ListView實(shí)現(xiàn)上拉加載更多和下拉刷新功能,介紹了ListView刷新原理及實(shí)現(xiàn)方法,感興趣的小伙伴們可以參考一下
    2016-05-05
  • Android程序開(kāi)發(fā)之獲取漢字的首字母

    Android程序開(kāi)發(fā)之獲取漢字的首字母

    獲取漢字首字母在android程序開(kāi)發(fā)中經(jīng)常用到,下面通過(guò)本文給大家介紹Android程序開(kāi)發(fā)之獲取漢字的首字母,需要的朋友參考下吧
    2016-03-03
  • Android Zipalign工具優(yōu)化Android APK應(yīng)用

    Android Zipalign工具優(yōu)化Android APK應(yīng)用

    本文主要介紹Android Zipalign工具優(yōu)化Android APK應(yīng)用,這里整理了相關(guān)資料及簡(jiǎn)單優(yōu)化實(shí)例,有需要的小伙伴可以參考下
    2016-09-09

最新評(píng)論