Android底部Sheet适应/缩小相关地图视图

11

尝试模仿当前Google Maps底部的栏。

我一直在尝试但都失败了,包括CollapsingToolbar、BottomSheet和自定义库。

我的目标:当BottomSheet滑动时,让地图视图适应其大小和相机,使底部表单不会滑过地图,而是使地图适合剩余的空间。

可以查看这个视频,了解我的意思(我指的不是缩放功能)。


你找到解决方案了吗? - pepela
1
是的,我使用了一个BottomSheet来滑动、展开和折叠我的内容,并将地图保留在后面。为了适应地图(大小和相机中心),我在BottomSheets onSlide和onStateChanged中放置了一些代码。只需相应地调整地图填充即可完成这两个操作。看起来非常流畅和酷炫;-) - EssenceBlue
你能分享一下地图和底部滑动的代码片段吗? - ralphgabb
@ralphgabb 请查看下面的完整答案。 - EssenceBlue
@EssenceBlue 将会尝试。谢谢。 - ralphgabb
2个回答

7
我使用的 BottomBar 库已被弃用。但也许我的代码能给你一个思路。

我是这样处理 BottomSheet 的 onSlide 事件的:

@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
    switch (bssBehavior.getState()) {
        case BottomSheetBehavior.STATE_DRAGGING:
            setMapPaddingBotttom(slideOffset);
            searchVM.map.moveCamera(CameraUpdateFactory.newLatLng(lastValidMapCenter));
            break;
        case BottomSheetBehavior.STATE_SETTLING:
            setMapPaddingBotttom(slideOffset);
            searchVM.map.moveCamera(CameraUpdateFactory.newLatLng(lastValidMapCenter));
            break;
        case BottomSheetBehavior.STATE_HIDDEN:
            break;
        case BottomSheetBehavior.STATE_EXPANDED:
            break;
        case BottomSheetBehavior.STATE_COLLAPSED:
            break;
    }

通过改变填充方式,平滑地调整了地图大小。为了相应地计算它,我使用了类似以下的方法。
private void setMapPaddingBotttom(Float offset) {
    //From 0.0 (min) - 1.0 (max)
    Float maxMapPaddingBottom = bsExpanded - bsCollapsed;
    //left,top,right,bottom
    searchVM.map.setPadding(0, 0, 0, Math.round(offset * maxMapPaddingBottom));
}

变量 bsExpanded - bsCollapsed 是什么意思? - Marlon López
1
maxMapPaddingBottom是地图填充的最大高度(以像素为单位),因此通过将其与百分比偏移量相乘,您可以得到相应的像素值。而bsExpanded是底部工作表展开时的高度(以像素为单位),而bsCollapsed则是折叠时的大小,并仅显示带有例如一些按钮或任何指示您可以向上滑动以展开它的细长条形。 - EssenceBlue

2
这里有一个完整的示例,可以实现当顶部的BottomSheet移动/滑动时,Google Map的padding会自动调整大小的效果。这样,地图上的Google标志始终会与bottomsheet一起移动。
  1. 定义您的布局。通常我们会在一个包含MapFragment和一个覆盖在其上方的BottomSheet布局的activity/fragment中使用它。这是一个带有全屏地图的示例:
<androidx.coordinatorlayout.widget.CoordinatorLayout
    android:id="@+id/root_coordinator_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        class="com.google.android.gms.maps.SupportMapFragment"
        android:id="@+id/map_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <LinearLayout
        android:id="@+id/bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/bottom_sheet_behavior"
        android:elevation="4dp"
        app:behavior_peekHeight="420dp"
        android:orientation="vertical">

        <!-- Your bottom sheet's content-->

    </LinearLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>
  1. 设置您的活动或片段。类似于@EssenceBlue发布的想法,我们使用底部工作表的onSlide()回调,并在每次调整地图的底部填充时进行调整。
class MapWithSheetActivity : AppCompatActivity() {

    private var googleMap: GoogleMap? = null
    private var bottomSheetContainer: CoordinatorLayout? = null
    private var bottomSheetLayout: LinearLayout? = null


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_booking_detail)
        this.bottomSheetLayout = findViewById<LinearLayout>(R.id.bottom_sheet)
        this.bottomSheetContainer = findViewById<CoordinatorLayout>(R.id.root_coordinator_layout)
        initMap()
        initBottomSheet()
    }

    private fun initMap() {
        val mapFragment = supportFragmentManager.findFragmentById(R.id.map_fragment) as? SupportMapFragment
        mapFragment?.getMapAsync { googleMap ->
            this.googleMap = googleMap
        }
    }

    private fun initBottomSheet() {
        val bottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.bottom_sheet))
        bottomSheetBehavior.addBottomSheetCallback(object :
            BottomSheetBehavior.BottomSheetCallback() {
            override fun onSlide(bottomSheet: View, slideOffset: Float) {
                when (bottomSheetBehavior.state) {
                    BottomSheetBehavior.STATE_DRAGGING, BottomSheetBehavior.STATE_SETTLING -> {
                        adjustMapPaddingToBottomSheet()
                    }
                    else -> {
                        // No adjustment needed on other slide states.
                    }
                }
            }

            override fun onStateChanged(bottomSheet: View, newState: Int) {
                // Needed only in case you manually change the bottomsheet's state in code somewhere.
                when (newState) {
                    BottomSheetBehavior.STATE_EXPANDED -> {
                        // Nothing to do here
                    }
                    else -> {
                        adjustMapPaddingToBottomSheet()
                    }
                }
            }

        })
    }

    private fun adjustMapPaddingToBottomSheet() {
        googleMap?.let { map ->
            if (this.bottomSheetContainer != null && this.bottomSheetLayout != null) {
                val bottomSheetContainerHeight = this.bottomSheetContainer.height
                val currentBottomSheetTop = this.bottomSheetLayout.top
                map.setPadding(
                    0, // left
                    0, // top
                    0, // right
                    bottomSheetContainerHeight - currentBottomSheetTop // bottom
                )
            }
        }
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接