Skip to content

اضافه‌ کردن نشانگر

Mohammad-Reza Azizi edited this page Jul 29, 2018 · 2 revisions

پروژه‌ی آموزشی نحوه‌استفاده از SDK نقشه نشان

اضافه‌کردن نشانگر

در این آموزش هدف ما اضافه کردن یک نشانگر بر روی نقطه‌ای از نقشه است که کاربر بر روی آن نقطه لمس طولانی کرده است.

  • activity_add_marker.xml:

فایل لی‌اوت این بخش صرفا شامل یک نقشه از کلاس org.neshan.ui.MapView است.

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    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=".AddMarker">

    <org.neshan.ui.MapView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/map"/>
</android.support.constraint.ConstraintLayout>


  • AddMarker.java:

برای این که نقشه همواره در لایه شماره ۰ باشد، ثابتی به نام BASE_MAP_INDEX تعریف شده است که. متغیری از نوع MapView جهت دریافت المان نقشه که در فایل لی‌اوت وجود دارد و متغیری از نوع VectorElementLayer جهت افزودن همه نشان‌گرهایی که در طول برنامه ایجاد می‌شود به آن ، در نظر گرفته شده‌است.

    // layer number in which map is added
    final int BASE_MAP_INDEX = 0;

    // map UI element
    MapView map;

    // You can add some elements to a VectorElementLayer
    VectorElementLayer markerLayer;

متد initLayoutRefrences جهت مقداردهی اولیه کردن به تمامی المان‌های مربوط به رابط کاربری نوشته شده‌است. به دلیل این که لازم است تا المان اندرویدی نقشه نشان ابتدا به طور کامل ایجاد شود و سپس با آن تعامل برقرار شود (متدهای مختلف بر روی المان نقشه اجرا شود)، تمامی متدهای مربوط به رابط کاربری باید در متد onStart انجام شوند.

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // starting app in full screen
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_add_marker);
    }
    @Override
    protected void onStart() {
        super.onStart();
        // everything related to ui is initialized here
        initLayoutReferences();
    }

در این متد ابتدا متد initViews و سپس متدinitMap صدا زده می شود که متد اول برای دریافت المان‌های رابط کاربری و متد دوم برای مقداردهی اولیه نقشه به کار می‌رود که هر دو در ادامه توضیح داده خواهند شد.

سپس یک MapEventListener بر روی نقشه set می‌شود. هنگامی که هر رویدادی، مثال لمس عادی، دوبار لمس، لمس طولانی و ...، بر روی نقشه انجام شود، تابع onMapClicked صدا زده می‌شود. در این تابع و با استفاده از صدا زدن متد getClickType بر روی ورودی تابع onMapClicked می‌توان نوع لمس بر روی نقشه را تشخیص داد.

در این قطعه کد، پس از تشخیص لمس طولانی بر روی بخشی از نقشه، موقعیت جغرافیایی آن با استفاده از متد getClickPos به دست آمده و با استفاده از صدا زدن تابع AddMarker - که در ادامه توضیح داده خواهد شد - نشانگری در آن موقعیت جغرافیایی بر روی نقشه نشان داده خواهد شد.

    // Initializing layout references (views, map and map events)
    private void initLayoutReferences() {
        // Initializing views
        initViews();
        // Initializing mapView element
        initMap();

        // when long clicked on map, a marker is added in clicked location
        // MapEventListener gets all events on map, including single tap, double tap, long press, etc
        // we should check event type by calling getClickType() on mapClickInfo (from ClickData class)
        map.setMapEventListener(new MapEventListener(){
            @Override
            public void onMapClicked(ClickData mapClickInfo){
                if(mapClickInfo.getClickType() == ClickType.CLICK_TYPE_LONG) {
                    // by calling getClickPos(), we can get position of clicking (or tapping)
                    LngLat clickedLocation = mapClickInfo.getClickPos();
                    // addMarker adds a marker (pretty self explanatory :D) to the clicked location
                    addMarker(clickedLocation);
                }
            }
        });
    }

در این متد تمامی المان‌های مربوط به رابط کاربری - که در اینجا فقط نقشه نشان است - دریافت شده و به متغیری نسبت داده می‌شوند.

    // We use findViewByID for every element in our layout file here
    private void initViews(){
        map = findViewById(R.id.map);
    }

در این متد در ابتدا یک VectorElementLayer ایجاد شده و به متغیر markerLayer نسبت داده می‌شود و سپس این لایه ایجاد شده به لایه‌های نقشه (map) اضافه می‌شود.

در ادامه بازه بزرگنمایی نقشه مشخص شده و سپس یک BaseMap با ظاهر STANDARD_DAY ایجاد شده و به لایه شماره BASE_MAP_INDEX - که مقدار آن را در ابتدای این فایل برابر با ۰ در نظر گرفته شده - اضافه می‌شود.

سپس نقشه بر روی نقطه‌ ثابتی تمرکز کرده و مقدار بزرگنمایی آن در این تمرکز مشخص می‌شود.

    // Initializing map
    private void initMap(){
        // Creating a VectorElementLayer(called markerLayer) to add all markers to it and adding it to map's layers
        markerLayer = NeshanServices.createVectorElementLayer();
        map.getLayers().add(markerLayer);

        // add Standard_day map to layer BASE_MAP_INDEX
        map.getOptions().setZoomRange(new Range(4.5f, 18f));
        map.getLayers().insert(BASE_MAP_INDEX, NeshanServices.createBaseMap(NeshanMapStyle.STANDARD_DAY));

        // Setting map focal position to a fixed position and setting camera zoom
        map.setFocalPointPosition(new LngLat(51.330743, 35.767234),0 );
        map.setZoom(14,0);
    }

این متد یک نقطه جغرافیایی از نوع LngLat دریافت می‌کند.

ابتدا تمامی نشان‌گرهایی که در لایه markerLayer بودند پاک‌ می‌شوند.

سپس برای ساختن انیمیشنِ قرارداده شدن نشانگر بر روی نقشه، ابتدا یک شی از کلاس AnimationStyleBuilder ساخته و ویژگی‌های انیمیشن از جمله اندازه آن، نوع محو شدن و مدت‌زمان‌های شروع و پایان انیمیشن در این شی set می‌شود. در نهایت با صدا زدن متد buildStyle بر روی این شی، شی‌ای از نوع AnimationStyle ساخته می‌شود.

برای ایجاد style نشان‌گر نیز ابتدا یک شی از کلاس MarkerStyleCreator ساخته می‌شود، سپس ویژگی‌های نشان‌گر مورد نظر بر روی آن set می‌شود. از جمله این ویژگی‌ها، نوع انیمیشن آن است که در بخش قبل ساخته شده است. در نهایت با صدا زدن متد buildStyle شی ای از نوع MarkerStyle به وجود می‌آید.

در ادامه یک شی از نوع Marker ساخته می‌شود که سازنده آن، مکان درج نشان‌گر و style آن را به عنوان ورودی دریافت می‌کند.

نشان‌گر ساخته شده به لایه نشان‌گرها یا markerLayer اضافه شده است و با این کار‌ نشان‌گر بر روی نقشه نمایش داده می‌شود.

    // This method gets a LngLat as input and adds a marker on that position
    private void addMarker(LngLat loc){
        // First, we should clear every marker that is currently located on map
        markerLayer.clear();

        // Creating animation for marker. We should use an object of type AnimationStyleBuilder, set
        // all animation features on it and then call buildStyle() method that returns an object of type
        // AnimationStyle
        AnimationStyleBuilder animStBl = new AnimationStyleBuilder();
        animStBl.setFadeAnimationType(AnimationType.ANIMATION_TYPE_SMOOTHSTEP);
        animStBl.setSizeAnimationType(AnimationType.ANIMATION_TYPE_SPRING);
        animStBl.setPhaseInDuration(0.5f);
        animStBl.setPhaseOutDuration(0.5f);
        AnimationStyle animSt = animStBl.buildStyle();

        // Creating marker style. We should use an object of type MarkerStyleCreator, set all features on it
        // and then call buildStyle method on it. This method returns an object of type MarkerStyle
        MarkerStyleCreator markStCr = new MarkerStyleCreator();
        markStCr.setSize(20f);
        markStCr.setBitmap(BitmapUtils.createBitmapFromAndroidBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.ic_marker)));
        // AnimationStyle object - that was created before - is used here
        markStCr.setAnimationStyle(animSt);
        MarkerStyle markSt = markStCr.buildStyle();

        // Creating marker
        Marker marker = new Marker(loc, markSt);

        // Adding marker to markerLayer, or showing marker on map!
        markerLayer.add(marker);
    }


صفحه قبل (راه‌اندازی اپلیکیشن)

صفحه بعد (رسم خط)