Центр Google Maps Circle на экране - PullRequest
0 голосов
/ 03 сентября 2018

Я нарисовал круг на карте Google Maps следующим образом:

    var circle = CircleOptions().center(googleMap?.cameraPosition?.target)
            .radius(MAX_RADIUS.toDouble())
            .fillColor(ContextCompat.getColor(ctx, R.color.mapCircle))
            .strokeWidth(0f)
    Timber.w("Painting circle!")
    staticCircle = googleMap?.addCircle(circle)

Теперь я хочу сохранить этот круг по центру на карте, поэтому я сделал это:

 googleMap?.setOnCameraMoveListener {
            var center = googleMap?.cameraPosition?.target

            if (center != null) {
                Timber.v("Centering circle in $center")
                animatedCircle?.center = center
                staticCircle?.center = center
            }
        }

Однако движение прерывистое, а также, когда происходит автоматическое масштабирование, круг перемещается вместе с камерой, а не ждет, пока она установится.

Есть ли лучший способ сделать это?

Ответы [ 2 ]

0 голосов
/ 03 сентября 2018

Лучше использовать MapView на основе пользовательское представление с переопределением 'dispatchDraw ()' (потому что MapView равно ViewGroup) что нарисовать круг над его содержанием. И радиус круга должен быть пересчитан для текущего уровня масштабирования. Примерно так:

public class CustomMapView extends MapView implements OnMapReadyCallback {

    private OnMapReadyCallback mMapReadyCallback;
    private GoogleMap mGoogleMap;
    private int mRadiusInMeters = 500;
    private Paint mPaintCircle;

    public CustomMapView(@NonNull Context context) {
        super(context);
        init();
    }

    public CustomMapView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CustomMapView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public CustomMapView(@NonNull Context context, @Nullable GoogleMapOptions options) {
        super(context, options);
        init();
    }

    @Override
    public void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        canvas.save();
        drawCircle(canvas);
        canvas.restore();
    }

    private void drawCircle(Canvas canvas) {
        if (mGoogleMap == null) {
            return;
        }

        VisibleRegion visibleRegion = mGoogleMap.getProjection().getVisibleRegion();
        LatLngBounds screenBounds = visibleRegion.latLngBounds;
        LatLng mapCenter = screenBounds.getCenter();
        final Point pointMapCenter = mGoogleMap.getProjection().toScreenLocation(mapCenter);
        final double meters_int_pixel = (Math.cos(mGoogleMap.getCameraPosition().target.latitude * Math.PI /180) * 2 * Math.PI * 6378137)
                / (256 * Math.pow(2, mGoogleMap.getCameraPosition().zoom));
        final int radius = (int)(mRadiusInMeters / meters_int_pixel);
        canvas.drawCircle(pointMapCenter.x, pointMapCenter.y, radius, mPaintCircle);
    }

    private void init() {
        setWillNotDraw(false);

        mPaintCircle = new Paint();
        mPaintCircle.setColor(Color.BLUE);
        mPaintCircle.setStyle(Paint.Style.FILL);
        mPaintCircle.setAlpha(90);
        mPaintCircle.setStrokeWidth(5);
    }

    @Override
    public void getMapAsync(OnMapReadyCallback callback) {
        mMapReadyCallback = callback;
        super.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mGoogleMap = googleMap;
        mGoogleMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {
            @Override
            public void onCameraMove() {
                invalidate();
            }
        });
        if (mMapReadyCallback != null) {
            mMapReadyCallback.onMapReady(googleMap);
        }
    }
}

И вы можете использовать это пользовательское представление в вашем MainActivity следующим образом:

public class MainActivity extends AppCompatActivity {

    private static final String MAP_VIEW_BUNDLE_KEY = "MapViewBundleKey";
    private CustomMapView mMapView;

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

        Bundle mapViewBundle = null;
        if (savedInstanceState != null) {
            mapViewBundle = savedInstanceState.getBundle(MAP_VIEW_BUNDLE_KEY);
        }

        mMapView = (CustomMapView) findViewById(R.id.mapview);
        mMapView.onCreate(mapViewBundle);
        mMapView.getMapAsync(new OnMapReadyCallback() {
            @Override
            public void onMapReady(GoogleMap googleMap) {
                mGoogleMap = googleMap;
            }
        });

    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        Bundle mapViewBundle = outState.getBundle(MAP_VIEW_BUNDLE_KEY);
        if (mapViewBundle == null) {
            mapViewBundle = new Bundle();
            outState.putBundle(MAP_VIEW_BUNDLE_KEY, mapViewBundle);
        }

        mMapView.onSaveInstanceState(mapViewBundle);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mMapView.onResume();
    }

    @Override
    protected void onStart() {
        super.onStart();
        mMapView.onStart();
    }

    @Override
    protected void onStop() {
        super.onStop();
        mMapView.onStop();
    }
    @Override
    protected void onPause() {
        mMapView.onPause();
        super.onPause();
    }
    @Override
    protected void onDestroy() {
        mMapView.onDestroy();
        super.onDestroy();
    }
    @Override
    public void onLowMemory() {
        super.onLowMemory();
        mMapView.onLowMemory();
    }

}

с файлом макета activity_main.xml как:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.test.just.googlemapsgeneral.views.CustomMapView
        android:id="@+id/mapview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        />

</RelativeLayout>
0 голосов
/ 03 сентября 2018

Как насчет использования setOnCameraIdleListener вместо setOnCameraMoveListener ? Обратный вызов сработает только после окончания движения камеры / увеличения

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...