Android运动布局无法正常工作

我是motionlayout的新手,并一直在线学习this之类的各种教程,以了解其工作原理。简而言之,我知道它基本上为constraintSets设置了动画,您有startend constraintSet可以用KeyFrameSets进一步自定义。我有这个布局

Android运动布局无法正常工作

我想模仿Lyft's bottom sheet

Android运动布局无法正常工作

在我的布局中,Where are you going按钮应该随着搜索目标textInputs的淡入而逐渐淡出。底部的recyclerview应该保留保存的addresses ,它不会受到影响。我尝试使用标准的bottomsheet来实现该实现,但是动画方面遇到了挑战,它的外观有点怪异flickering,所以我决定使用普通视图的MotionLayout

我的bottomsheet布局如下

<com.google.android.material.card.MaterialCardView 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:id="@+id/cardChooseAddressBottomSheet"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clickable="true"
    app:shapeAppearance="@style/ShapeAppearanceRoundedLargeTopCorners">



    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/bottomSheetConstraintLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="@dimen/activity_horizontal_margin"
        android:layout_marginRight="@dimen/activity_horizontal_margin"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">



        <ImageView
            android:id="@+id/swipeUpHandle"
            android:layout_width="50dp"
            android:layout_height="30dp"
            android:layout_gravity="center"
            android:background="@drawable/ic_swipe_up_handle"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />



        <com.google.android.material.textview.MaterialTextView
            android:id="@+id/hiThere"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/medium_margin"
            android:text="@string/hi_there"
            android:textAppearance="@style/h6_headline"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/swipeUpHandle"
            />


        <com.google.android.material.button.MaterialButton
            android:id="@+id/btnSearch"
            style="@style/Widget.MaterialComponents.Button.OutlinedButton"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:layout_marginTop="@dimen/medium_margin"
            android:gravity="start|center_vertical"
            android:letterSpacing="0.0"
            android:text="@string/where_are_you_going"
            android:textAllCaps="false"
            android:textAppearance="@style/subtitle1"
            android:textColor="@android:color/darker_gray"
            app:backgroundTint="@android:color/white"
            app:icon="@drawable/ic_search"
            app:iconTint="@android:color/black"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/hiThere"
            app:shapeAppearanceOverlay="@style/ShapeAppearanceRoundedMediumAllCorners" />



        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:id="@+id/addressViews"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/btnSearch">



            <com.google.android.material.textfield.TextInputLayout
                android:id="@+id/inputOrigin"
                style="@style/textInput"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/medium_margin"
                android:hint="@string/search_destination"
                android:textColorHint="@android:color/darker_gray"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent">

                <com.google.android.material.textfield.TextInputEditText
                    android:id="@+id/edtOrigin"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:inputType="text"
                    android:textAppearance="@style/subtitle1"
                    android:textColor="@android:color/white" />

            </com.google.android.material.textfield.TextInputLayout>

            <com.google.android.material.textfield.TextInputLayout
                android:id="@+id/inputDestination"
                style="@style/textInput"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/medium_margin"
                android:hint="@string/search_destination"
                android:textColorHint="@android:color/darker_gray"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/inputOrigin">

                <com.google.android.material.textfield.TextInputEditText
                    android:id="@+id/edtDestination"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:inputType="text"
                    android:textAppearance="@style/subtitle1"
                    android:textColor="@android:color/white" />

            </com.google.android.material.textfield.TextInputLayout>


        </androidx.constraintlayout.widget.ConstraintLayout>

        <androidx.recyclerview.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:id="@+id/recyclerAddresses"
            android:layout_marginTop="@dimen/medium_margin"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/addressViews"
            tools:listitem="@layout/recycler_view_item" />
    </androidx.constraintlayout.widget.ConstraintLayout>

</com.google.android.material.card.MaterialCardView>

我在其中包含bottomsheet的父布局如下

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout 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:id="@+id/motionLayout"
    app:layoutDescription="@xml/taxi_bottomsheet_scene"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


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



    <include
        layout="@layout/choose_destination_bottom_sheet_layout"/>

</androidx.constraintlayout.motion.widget.MotionLayout>

最后我的taxi_bottomsheet_scene运动场景是

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">



    <Transition
        app:constraintSetEnd="@+id/expanded"
        app:constraintSetStart="@+id/collapsed"
        app:duration="1000">

        <OnSwipe
            app:touchAnchorId="@+id/btnSearch"
            app:touchAnchorSide="top"
            app:dragDirection="dragUp"/>


    </Transition>


    <ConstraintSet android:id="@+id/expanded">

        <Constraint
            android:id="@+id/cardChooseAddressBottomSheet"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHeight_percent="1"
            app:layout_constraintHorizontal_bias="1.0"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0" />



        <Constraint
            android:id="@+id/addressViews"
            app:layout_constraintHeight_percent="1"/>


        <Constraint
            android:id="@+id/btnSearch"
            app:layout_constraintHeight_percent="0"/>

    </ConstraintSet>




    <ConstraintSet android:id="@+id/collapsed">

        <Constraint
            android:id="@+id/cardChooseAddressBottomSheet"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHeight_percent="0.4"
            app:layout_constraintHorizontal_bias="1.0"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="1.0"  />


        <Constraint
            android:id="@+id/addressViews"
            app:layout_constraintHeight_percent="0.0"/>



        <Constraint
            android:id="@+id/btnSearch"
            app:layout_constraintHeight_percent="0.0"/>
    </ConstraintSet>





</MotionScene>

当我启动该应用程序时,我无法使底片向上滑动,它根本没有任何响应。我注意到的一件事是,在添加了app:layoutDescription="@xml/taxi_bottomsheet_scene"属性之后,底部工作表的大小更改为我在constraintSetStart中指定的大小,但是addressViews视图却没有。

所以我的布局看起来像

Android运动布局无法正常工作

所以我的问题是,我的底表在不响应我的swipesaddressViews在初始状态下消失的地方出了错?

super_1987cl 回答:Android运动布局无法正常工作

我终于设法通过MotionLayoutCoordinatorLayout使其起作用。我只会发布Coordinator解决方案,因为它很长而且没有时间,如果有人需要它,请发表评论,然后我会发布。

我创建了1. The main layout with the map2. Top bar with the to and from address EditTexts3. The bottom layout这3种布局,它们向上滑动并显示了顶部栏。

使用CoordinatorLayout的解决方案1 ​​

  1. 顶部栏

     

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:focusable="true"
        android:layout_marginBottom="@dimen/medium_margin"
        app:layout_scrollFlags="noScroll">
    
    
        <com.google.android.material.appbar.MaterialToolbar
            android:id="@+id/topToolBar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:navigationIcon="@drawable/ic_arrow_back_black_24dp" />
    
    
        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/addressViews"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_marginStart="@dimen/activity_horizontal_margin"
            android:layout_marginEnd="@dimen/activity_horizontal_margin"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/topToolBar">
    
    
            <androidx.appcompat.widget.AppCompatImageView
                android:id="@+id/imgOrigin"
                android:layout_width="@dimen/activity_horizontal_margin"
                android:layout_height="@dimen/activity_horizontal_margin"
                android:layout_marginStart="@dimen/medium_margin"
                android:layout_marginEnd="@dimen/medium_margin"
                app:layout_constraintBottom_toBottomOf="@+id/inputOrigin"
                app:layout_constraintEnd_toStartOf="@+id/inputOrigin"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="@+id/inputOrigin"
                app:srcCompat="@drawable/ic_origin"
                app:tint="@color/colorAccent" />
    
    
            <View
                android:layout_width="2dp"
                android:layout_height="0dp"
                android:layout_marginTop="@dimen/xsmall_margin"
                android:layout_marginBottom="@dimen/xsmall_margin"
                android:background="@drawable/accent_to_color_primary_dark__negative_90_gradient"
                app:layout_constraintBottom_toTopOf="@+id/imgDestination"
                app:layout_constraintEnd_toEndOf="@+id/imgOrigin"
                app:layout_constraintStart_toStartOf="@+id/imgOrigin"
                app:layout_constraintTop_toBottomOf="@+id/imgOrigin" />
    
            <com.google.android.material.textfield.TextInputLayout
                android:id="@+id/inputOrigin"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/medium_margin"
                android:hint="@string/pick_up_location"
                android:marqueeRepeatLimit="marquee_forever"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toEndOf="@+id/imgOrigin"
                app:layout_constraintTop_toTopOf="parent">
    
                <com.google.android.material.textfield.TextInputEditText
                    android:id="@+id/edtOrigin"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="@color/white"
                    android:inputType="textPostalAddress"
                    android:singleLine="true"
                    android:textAppearance="@style/subtitle1" />
    
            </com.google.android.material.textfield.TextInputLayout>
    
    
            <androidx.appcompat.widget.AppCompatImageView
                android:id="@+id/imgDestination"
                android:layout_width="@dimen/activity_horizontal_margin"
                android:layout_height="@dimen/activity_horizontal_margin"
                android:layout_marginStart="@dimen/medium_margin"
                android:layout_marginEnd="@dimen/medium_margin"
                app:layout_constraintBottom_toBottomOf="@+id/inputDestination"
                app:layout_constraintEnd_toStartOf="@+id/inputDestination"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="@+id/inputDestination"
                app:srcCompat="@drawable/ic_destination"
                app:tint="@color/colorPrimaryDark" />
    
            <com.google.android.material.textfield.TextInputLayout
                android:id="@+id/inputDestination"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/medium_margin"
                android:hint="@string/search_destination"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toEndOf="@+id/imgDestination"
                app:layout_constraintTop_toBottomOf="@id/inputOrigin">
    
                <com.google.android.material.textfield.TextInputEditText
                    android:id="@+id/edtDestination"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="@color/white"
                    android:inputType="textPostalAddress"
                    android:singleLine="true"
                    android:textAppearance="@style/subtitle1" />
    
            </com.google.android.material.textfield.TextInputLayout>
    
        </androidx.constraintlayout.widget.ConstraintLayout>
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
    </com.google.android.material.appbar.AppBarLayout>
    
  2. 底部布局就像一个底部纸

    <com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/cardChooseAddressBottomSheet"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:cardBackgroundColor="@color/white"
    app:behavior_hideable="false"
    app:layout_behavior="@string/bottom_sheet_behavior">
    
    
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">
    
    
    
        <ImageView
            android:id="@+id/swipeUpHandle"
            android:layout_width="35dp"
            android:layout_height="30dp"
            android:layout_gravity="center"
            android:layout_marginLeft="@dimen/activity_horizontal_margin"
            android:layout_marginRight="@dimen/activity_horizontal_margin"
            android:background="@drawable/ic_swipe_up_handle"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
    
        <com.google.android.material.textview.MaterialTextView
            android:id="@+id/hiThere"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/hi_there"
            android:layout_marginLeft="@dimen/activity_horizontal_margin"
            android:layout_marginRight="@dimen/activity_horizontal_margin"
            android:textAppearance="@style/h6_headline"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/swipeUpHandle" />
    
    
        <com.google.android.material.button.MaterialButton
            android:id="@+id/btnSearch"
            style="@style/Widget.MaterialComponents.Button.OutlinedButton"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:layout_marginLeft="@dimen/activity_horizontal_margin"
            android:layout_marginRight="@dimen/activity_horizontal_margin"
            android:gravity="start|center_vertical"
            android:letterSpacing="0.0"
            android:text="@string/where_are_you_going"
            android:textAllCaps="false"
            android:textAppearance="@style/subtitle1"
            android:textColor="@android:color/darker_gray"
            app:backgroundTint="@android:color/white"
            app:icon="@drawable/ic_search"
            app:iconSize="@dimen/medium_icon"
            app:iconTint="@color/colorAccent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/hiThere"
            app:shapeAppearanceOverlay="@style/ShapeAppearanceRoundedMediumAllCorners" />
    
    
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerAddresses"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/btnSearch" />
    
    
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerSearchAddresses"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:background="@color/white"
            android:visibility="gone"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/btnSearch" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
    </com.google.android.material.card.MaterialCardView>
    
  3. 最后是我的地图布局中包含的两个布局

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:id="@+id/coordinator"
        android:layout_height="match_parent">
    
        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
    
            <fragment
                android:id="@+id/map"
                android:name="com.google.android.gms.maps.SupportMapFragment"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHeight_percent="0.67"
                app:layout_constraintHorizontal_bias="0.0"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />
    
            <androidx.appcompat.widget.AppCompatImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/imgMapCenter"
                android:layout_marginBottom="@dimen/xlarge_margin"
                android:visibility="invisible"
                android:tint="@color/colorAccent"
                app:layout_constraintBottom_toBottomOf="@id/map"
                app:layout_constraintEnd_toEndOf="@id/map"
                app:layout_constraintStart_toStartOf="@id/map"
                app:layout_constraintTop_toTopOf="@id/map"
                app:srcCompat="@drawable/ic_destination" />
        </androidx.constraintlayout.widget.ConstraintLayout>
    
    
        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/fabMyLocation"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/activity_horizontal_margin"
            app:backgroundTint="@color/white"
            app:fabSize="mini"
            app:layout_anchor="@id/cardChooseAddressBottomSheet"
            app:layout_anchorGravity="top|right"
            app:srcCompat="@drawable/ic_origin"
            app:tint="@color/colorAccent" />
        <include layout="@layout/taxi_fragment_set_destination_top_bar" />
    
        <include layout="@layout/taxi_fragment_bottom_sheet_addresses_layout" />
    
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    

还有我的片段

   final private BottomSheetBehavior.BottomSheetCallback addressBottomSheetCallBack = new BottomSheetBehavior.BottomSheetCallback() {
        @Override
        public void onStateChanged(@NonNull View bottomSheet,int newState) {
            switch (newState) {
                case BottomSheetBehavior.STATE_HIDDEN:
                    break;

                case BottomSheetBehavior.STATE_SETTLING:
                    break;

                case BottomSheetBehavior.STATE_EXPANDED:
                    if (!allPermissionsGranted())
                        requestForLocationPermissions();
                    topAddressBar.setVisibility(Visibility.VISIBLE);
                     fabMyLocation.hide();
                    break;

                case BottomSheetBehavior.STATE_COLLAPSED:
                    if (!allPermissionsGranted())
                        requestForLocationPermissions();
                    topAddressBar.setVisibility(Visibility.INVISIBLE);
                    fabMyLocation.show();
                    break;

                case BottomSheetBehavior.STATE_DRAGGING:
                    break;

                case BottomSheetBehavior.STATE_HALF_EXPANDED:
                    break;
            }
        }



   BottomSheetBehavior addressBottomSheetBehavior = BottomSheetBehavior.from(cardChooseAddressBottomSheet);

      topAddressBar.post(() -> {
            CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) cardChooseAddressBottomSheet.getLayoutParams();
            layoutParams.height = ((Resources.getSystem().getDisplayMetrics().heightPixels + (int) utils.percentageOf(62,btnSearch.getMeasuredHeight())) - topAddressBar.getMeasuredHeight());
        });


        addressBottomSheetBehavior.setPeekHeight((int) utils.percentageOf(29,Resources.getSystem().getDisplayMetrics().heightPixels),true);
        addressBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);


        topToolBar.setNavigationOnClickListener(view12 -> {
            if (addressBottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED) {
                utopAddressBar.setVisibility(INVISIBLE);
                addressBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
            } else
                Navigation.findNavController(view12).navigateUp();
        });

        addressBottomSheetBehavior.addBottomSheetCallback(addressBottomSheetCallBack);

是否在INVISIBLE上使用GONE而不是topAddressBar?这是因为根据我的假设,每次我调用GONE时,布局都会理想地recalculate,并且地图会闪烁,以阻止我不得不使用invisible,因为布局不会缩小,反而仍然占用了相同的空间,但不可见。

还请注意,我要添加填充cardChooseAddressBottomSheet.getLayoutParams(),这是因为我需要工作表不要在topAddressBar下过深,以免隐藏我的recyclerview内容。当前的填充确保了recyclerview完全可见,并且其顶部的所有其他内容都位于topAddressBar

之下
本文链接:https://www.f2er.com/3146647.html

大家都在问