Android Google Map - выбор типа карты из меню FAB

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

Android Google Map - выбор типа карты из меню FAB

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

3
0
1 632
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

  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">
  1. Заполните представлениями для диалогового окна
  2. Установите видимость 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">
    
  3. В вашей деятельности установите для параметра Visibility значение View.Visibleon, нажав кнопку:

    fab.setOnClickListener{  
      cardview.visibility = View.VISIBLE
    }
    

Спасибо за помощь, дружище. Это помогло мне с моими идеями :) опубликовал свой ответ, который я наконец завершил.

NicCoe 28.08.2018 16:43

NicCoe, если пост Ро Раса помог, проголосуйте за него или примите его ответ

RonTLV 28.08.2018 16:45
Ответ принят как подходящий

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

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

Дополнительные очки:

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

Ресурсы


type_default.png

type_s satellite.png

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
    }
}

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


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

Другие вопросы по теме