مستندات جامع اندروید
نسخه 1.0.3
هدف این بخش از پروژه تغییر جهت دوربین (از حالتی که دوربین به سمت شمال نقشه است به جهتهای دیگر) است.
activity_change_camera_bearing.xml
:
در این صفحه، علاوه بر المان نقشه نشان، یک ConstraintLayout
دیگر نیز وجود دارد که درون آن یک CircularSeekBar
و چهار TextView
وجود دارد. در TextView
ها عبارتهای شمال، شرق، جنوب و غرب نوشته شده است. المان CircularSeekBar
نیز در کلاس CircularSeekBar.java
تعریف شده است.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.ChangeCameraBearing">
<org.neshan.mapsdk.MapView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/map"/>
<ToggleButton
android:checked="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/toggle_button_text_color"
android:textOff="تغییر جهت دوربین"
android:textOn="تغییر جهت دوربین"
android:elevation="8dp"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:drawableStart="@drawable/ic_change_tilt"
android:drawableTint="@color/toggle_button_text_color"
android:drawablePadding="8dp"
android:background="@drawable/toggle_button_bg"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:targetApi="m"
android:onClick="toggleCameraRotation"/>
<android.support.constraint.ConstraintLayout
android:layout_width="250dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:background="@drawable/rounded_white_bg"
android:padding="16dp"
android:layout_marginTop="32dp"
android:layout_marginStart="64dp"
android:layout_marginEnd="64dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<TextView
android:id="@+id/north_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/textPrimaryColor"
android:text="شمال"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<TextView
android:id="@+id/south_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/textPrimaryColor"
android:text="جنوب"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<TextView
android:id="@+id/west_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/textPrimaryColor"
android:text="غرب"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<TextView
android:id="@+id/east_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/textPrimaryColor"
android:text="شرق"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<org.neshan.sample.starter.custom_view.CircularSeekBar
android:id="@+id/bearing_seek_bar"
android:layout_width="100dp"
android:layout_height="100dp"
app:cs_move_outside_circle = "true"
app:cs_max = "360"
app:cs_progress = "0"
app:cs_circle_style = "round"
app:cs_circle_stroke_width = "16dp"
app:cs_pointer_stroke_width = "16dp"
app:cs_circle_color = "@color/darkPrimaryColor"
app:cs_circle_progress_color = "@color/lightPrimaryColor"
app:cs_pointer_color = "@color/accentColor"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintTop_toBottomOf="@id/north_label"
app:layout_constraintBottom_toTopOf="@id/south_label"
app:layout_constraintStart_toEndOf="@id/west_label"
app:layout_constraintEnd_toStartOf="@id/east_label"/>
</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>
ChangeCameraBearing.java
:
متد 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_change_camera_bearing);
}
@Override
protected void onStart() {
super.onStart();
// everything related to ui is initialized here
initLayoutReferences();
}
بر روی bearingSeekBar
یک CircularSeekBarChangeListener
ست شده است و هنگامی که تابع onProgressChanged
صدا زده میشود، مقدار progress
این تابع به ورودی متد setBearing
– که بر روی شی map
صدا زده میشود – داده میشود. این متد تغییر جهت دوربین را پیادهسازی کرده است.
برای همگامسازی زمانی که جهت نقشه، با استفاده از gesture های از پیشتعریف شده بر روی نقشه تغییر میکند با درجه ی نشان داده شده بر روی SeekBar
موجود در رابطه کاربری، یک OnCameraMoveListener
بر روی map
ست میشود. در متد Listener
مقدار تغییر جهت نقشه به مقدار قابل نمایش بر روی SeekBar
تبدیل میشود. به این صورت که در صورتی که میزان تغییر جهت نقشه کمتر از ۰ درجه باشد، این مقدار با ۳۶۰ جمع شده و در غیر این صورت، همان مقدار تغییر جهت نقشه در نظر گرفته میشود.
برای نمایش این میزان تغییر بر روی SeekBar
نخ رابط کاربری جدیدی ایجاد میشود و متد setProgress
بر روی bearingSeekBar
صدا زده میشود. دلیل استفاده از UIThread جدید در (تغییر زاویه دوربین) توضیح داده شدهاست.
// Initializing layout references (views, map and map events)
private void initLayoutReferences() {
// Initializing views
initViews();
// Initializing mapView element
initMap();
// connect bearing seek bar to camera
bearingSeekBar.setOnSeekBarChangeListener(new CircularSeekBar.OnCircularSeekBarChangeListener() {
@Override
public void onProgressChanged(CircularSeekBar circularSeekBar, float progress, boolean fromUser) {
// change camera bearing programmatically
map.setBearing(progress, 0f);
}
@Override
public void onStopTrackingTouch(CircularSeekBar seekBar) {
}
@Override
public void onStartTrackingTouch(CircularSeekBar seekBar) {
}
});
map.setOnCameraMoveListener(() -> {
// updating seek bar with new camera bearing value
if (map.getBearing() < 0) {
cameraBearing = (180 + map.getBearing()) + 180;
} else {
cameraBearing = map.getBearing();
}
// updating own ui element must run on ui thread not in map ui thread
runOnUiThread(new Runnable() {
@Override
public void run() {
bearingSeekBar.setProgress(cameraBearing);
}
});
});
}
هنگامی که ToggleButton
موجود در رابط کاربری، در حالت انتخاب شده باشد، با استفاده از شی Settings
که از صدا زدن متد getSettings
بر روی المان نقشه به دست میآید و صدا زدن متد setMapRotationEnabled
با ورودی true
امکان تغییر جهت دوربین فراهم میشود و در غیر این صورت، ورودی false
به این متد داده میشود و امکان تغییر جهت دوربین غیرفعال میشود.
public void toggleCameraRotation (View view){
ToggleButton toggleButton = (ToggleButton) view;
isCameraRotationEnable = !isCameraRotationEnable;
if (toggleButton.isChecked())
map.getSettings().setMapRotationEnabled(true);
else
map.getSettings().setMapRotationEnabled(false);
}