-
Notifications
You must be signed in to change notification settings - Fork 0
اضافه کردن نشانگر
در این آموزش هدف ما اضافه کردن یک نشانگر بر روی نقطهای از نقشه است که کاربر بر روی آن نقطه لمس طولانی کرده است.
-
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);
}