Android Google Map - выбор типа карты из меню FAB - PullRequest
0 голосов
/ 27 августа 2018

Я пытаюсь создать красивое меню для изменения типа карты, точно так же, как в Google Maps. Оно появляется при нажатии FAB слоев.Я не знаю, является ли это пользовательским меню FAB, или оно оживляет и открывает фрагмент.

Screenshot of Google Maps layers menu

Как этого добиться?

Ответы [ 2 ]

0 голосов
/ 28 августа 2018

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

Примечание: Это не совсем идеально, может выглядеть по-другому на некоторых других устройствах и не судитьмое кодирование слишком много (я новичок ... я могу провести рефакторинг, но он выполняет свою работу).

Дополнительные баллы:

  • Написано вKotlin
  • Уверен, требуется API 21+.Здесь не реализовано никакого обходного пути для более ранних версий
  • При открытии / закрытии представления выбора используется анимация с круговым раскрытием, вместо того, чтобы расширять Googles (мне больше нравится моя реализация)
  • Отсутствие оптимизации можетприводят к снижению производительности на младших устройствах

Ресурсы


enter image description here type_default.png

enter image description here type_s satellite.png

enter image description here type_terrain.png

rounded_rectangle.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#2962ff" />
    <corners android:radius="10dp" />
</shape>

ic_map_layers.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
    <path
        android:fillColor="#3C4043"
        android:pathData="M11.99,18.54l-7.37,-5.73L3,14.07l9,7 9,-7 -1.63,-1.27 
        -7.38,5.74zM12,16l7.36,-5.73L21,9l-9,-7 -9,7 1.63,1.27L12,16z"/>
</vector>

Файл макета карты


Код, указанный здесь, также был вложен в макет ограничения с картой и другими FAB, но если вы читаете это, я не думаю, что вам нужно знать, какпоместить карту в ...

<android.support.design.widget.FloatingActionButton
    android:id="@+id/map_type_FAB"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginEnd="24dp"
    android:layout_marginTop="24dp"
    android:clickable="true"
    android:focusable="true"
    app:backgroundTint="#FFF"
    app:fabSize="mini"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="@+id/map_view"
    app:rippleColor="#eff5ff"
    app:srcCompat="@drawable/ic_map_layers" />

<android.support.constraint.ConstraintLayout
    android:id="@+id/map_type_selection"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/map_type_background"
    android:elevation="6dp"
    android:padding="8dp"
    android:visibility="invisible"
    app:layout_constraintEnd_toEndOf="@+id/map_type_FAB"
    app:layout_constraintTop_toTopOf="@+id/map_type_FAB">


    <View
        android:id="@+id/map_type_default_background"
        android:layout_width="54dp"
        android:layout_height="54dp"
        android:background="@drawable/rounded_rectangle"
        android:visibility="invisible"
        app:layout_constraintBottom_toBottomOf="@+id/map_type_default"
        app:layout_constraintEnd_toEndOf="@+id/map_type_default"
        app:layout_constraintStart_toStartOf="@+id/map_type_default"
        app:layout_constraintTop_toTopOf="@+id/map_type_default" />

    <ImageButton
        android:id="@+id/map_type_default"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:background="@drawable/type_default"
        android:scaleType="fitCenter"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView13" />

    <View
        android:id="@+id/map_type_satellite_background"
        android:layout_width="54dp"
        android:layout_height="54dp"
        android:background="@drawable/rounded_rectangle"
        android:visibility="invisible"
        app:layout_constraintBottom_toBottomOf="@+id/map_type_satellite"
        app:layout_constraintEnd_toEndOf="@+id/map_type_satellite"
        app:layout_constraintStart_toStartOf="@+id/map_type_satellite"
        app:layout_constraintTop_toTopOf="@+id/map_type_satellite" />

    <ImageButton
        android:id="@+id/map_type_satellite"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginEnd="32dp"
        android:layout_marginStart="32dp"
        android:layout_marginTop="8dp"
        android:background="@drawable/type_satellite"
        android:scaleType="fitCenter"
        app:layout_constraintEnd_toStartOf="@+id/map_type_terrain"
        app:layout_constraintStart_toEndOf="@+id/map_type_default"
        app:layout_constraintTop_toBottomOf="@+id/textView13" />

    <View
        android:id="@+id/map_type_terrain_background"
        android:layout_width="54dp"
        android:layout_height="54dp"
        android:background="@drawable/rounded_rectangle"
        android:visibility="invisible"
        app:layout_constraintBottom_toBottomOf="@+id/map_type_terrain"
        app:layout_constraintEnd_toEndOf="@+id/map_type_terrain"
        app:layout_constraintStart_toStartOf="@+id/map_type_terrain"
        app:layout_constraintTop_toTopOf="@+id/map_type_terrain" />

    <ImageButton
        android:id="@+id/map_type_terrain"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginEnd="8dp"
        android:layout_marginTop="8dp"
        android:background="@drawable/type_terrain"
        android:scaleType="fitCenter"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView13" />

    <TextView
        android:id="@+id/textView13"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:fontFamily="sans-serif"
        android:text="Map Type"
        android:textAllCaps="true"
        android:textColor="@android:color/black"
        android:textSize="12sp"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/map_type_default_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="Default"
        android:textColor="#808080"
        android:textSize="12sp"
        app:layout_constraintEnd_toEndOf="@+id/map_type_default"
        app:layout_constraintStart_toStartOf="@+id/map_type_default"
        app:layout_constraintTop_toBottomOf="@+id/map_type_default" />

    <TextView
        android:id="@+id/map_type_satellite_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="Satellite"
        android:textColor="#808080"
        android:textSize="12sp"
        app:layout_constraintEnd_toEndOf="@+id/map_type_satellite"
        app:layout_constraintStart_toStartOf="@+id/map_type_satellite"
        app:layout_constraintTop_toBottomOf="@+id/map_type_satellite" />

    <TextView
        android:id="@+id/map_type_terrain_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="Terrain"
        android:textColor="#808080"
        android:textSize="12sp"
        app:layout_constraintEnd_toEndOf="@+id/map_type_terrain"
        app:layout_constraintStart_toStartOf="@+id/map_type_terrain"
        app:layout_constraintTop_toBottomOf="@+id/map_type_terrain" />

</android.support.constraint.ConstraintLayout>

Фрагмент карты


Фрагмент кода из моей функции onMapReady.Это часть, которая не самая красивая, но выполняет свою работу.

   override fun onMapReady(googleMap: GoogleMap) {

    // Initialise the map variable
    map = googleMap

    // When map is initially loaded, determine which map type option to 'select'
    when {
        map.mapType == GoogleMap.MAP_TYPE_SATELLITE -> {
            map_type_satellite_background.visibility = View.VISIBLE
            map_type_satellite_text.setTextColor(Color.BLUE)
        }
        map.mapType == GoogleMap.MAP_TYPE_TERRAIN -> {
            map_type_terrain_background.visibility = View.VISIBLE
            map_type_terrain_text.setTextColor(Color.BLUE)
        }
        else -> {
            map_type_default_background.visibility = View.VISIBLE
            map_type_default_text.setTextColor(Color.BLUE)
        }
    }

    // Set click listener on FAB to open the map type selection view
    mapTypeFAB.setOnClickListener {

        // Start animator to reveal the selection view, starting from the FAB itself
        val anim = ViewAnimationUtils.createCircularReveal(
                map_type_selection,
                map_type_selection.width - (map_type_FAB.width / 2),
                map_type_FAB.height / 2,
                map_type_FAB.width / 2f,
                map_type_selection.width.toFloat())
        anim.duration = 200
        anim.interpolator = AccelerateDecelerateInterpolator()

        anim.addListener(object : AnimatorListenerAdapter() {
            override fun onAnimationStart(animation: Animator?) {
                super.onAnimationEnd(animation)
                map_type_selection.visibility = View.VISIBLE
            }
        })

        anim.start()
        mapTypeFAB.visibility = View.INVISIBLE

    }

    // Set click listener on the map to close the map type selection view
    map.setOnMapClickListener {

        // Conduct the animation if the FAB is invisible (window open)
        if (map_type_FAB.visibility == View.INVISIBLE) {

            // Start animator close and finish at the FAB position
            val anim = ViewAnimationUtils.createCircularReveal(
                    map_type_selection,
                    map_type_selection.width - (map_type_FAB.width / 2),
                    map_type_FAB.height / 2,
                    map_type_selection.width.toFloat(),
                    map_type_FAB.width / 2f)
            anim.duration = 200
            anim.interpolator = AccelerateDecelerateInterpolator()

            anim.addListener(object : AnimatorListenerAdapter() {
                override fun onAnimationEnd(animation: Animator?) {
                    super.onAnimationEnd(animation)
                    map_type_selection.visibility = View.INVISIBLE
                }
            })

            // Set a delay to reveal the FAB. Looks better than revealing at end of animation
            Handler().postDelayed({
                kotlin.run {
                    mapTypeFAB.visibility = View.VISIBLE
                }
            }, 100)
            anim.start()
        }
    }

    // Handle selection of the Default map type
    map_type_default.setOnClickListener {
        map_type_default_background.visibility = View.VISIBLE
        map_type_satellite_background.visibility = View.INVISIBLE
        map_type_terrain_background.visibility = View.INVISIBLE
        map_type_default_text.setTextColor(Color.BLUE)
        map_type_satellite_text.setTextColor(Color.parseColor("#808080"))
        map_type_terrain_text.setTextColor(Color.parseColor("#808080"))
        map.mapType = GoogleMap.MAP_TYPE_NORMAL
    }

    // Handle selection of the Satellite map type
    map_type_satellite.setOnClickListener {
        map_type_default_background.visibility = View.INVISIBLE
        map_type_satellite_background.visibility = View.VISIBLE
        map_type_terrain_background.visibility = View.INVISIBLE
        map_type_default_text.setTextColor(Color.parseColor("#808080"))
        map_type_satellite_text.setTextColor(Color.BLUE)
        map_type_terrain_text.setTextColor(Color.parseColor("#808080"))
        map.mapType = GoogleMap.MAP_TYPE_SATELLITE
    }

    // Handle selection of the terrain map type
    map_type_terrain.setOnClickListener {
        map_type_default_background.visibility = View.INVISIBLE
        map_type_satellite_background.visibility = View.INVISIBLE
        map_type_terrain_background.visibility = View.VISIBLE
        map_type_default_text.setTextColor(Color.parseColor("#808080"))
        map_type_satellite_text.setTextColor(Color.parseColor("#808080"))
        map_type_terrain_text.setTextColor(Color.BLUE)
        map.mapType = GoogleMap.MAP_TYPE_TERRAIN
    }
}

Конечный результат


Это мой конецрезультат.Как я уже сказал, я только начинающий, все может быть лучше, но сейчас я очень доволен результатом.

enter image description here

0 голосов
/ 28 августа 2018

Самое простое решение, о котором я могу подумать сейчас, это:

  1. Добавить <CardView> к вашему макету:
    ...
   <android.support.design.widget.FloatingActionButton 
      android:id="@+id/fab">  

   <android.support.v7.widget.CardView
      android:id="@+id/cardview"
      app:layout_constraintEnd_toEndOf="@+id/fab"
      app:layout_constraintTop_toTopOf="@+id/fab">
Заполнить представлениями для диалогового окна

Установить видимость на View.GONE:

 <android.support.v7.widget.CardView
    android:id="@+id/cardview"
    app:layout_constraintEnd_toEndOf="@+id/fab"
    app:layout_constraintTop_toTopOf="@+id/fab"
    android:visibility="gone">

В своей деятельности установите Видимость на View.Visible внажатие кнопки:

fab.setOnClickListener{  
  cardview.visibility = View.VISIBLE
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...