MotionLayout练习


效果

MotionScene

<?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">
    <ConstraintSet
        android:id="@+id/start">
        <Constraint
            android:id="@+id/music_control_background"
            >
            <Layout
                android:layout_width="match_parent"
                android:layout_height="50dp"
                app:layout_constraintBottom_toTopOf="@id/bottom_navi"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                />
        </Constraint>
        <Constraint
            android:id="@+id/profile_photo"
            >
            <Layout
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginStart="20dp"
                app:layout_constraintBottom_toBottomOf="@+id/music_control_background"
                app:layout_constraintStart_toStartOf="@id/music_control_background"
                app:layout_constraintTop_toTopOf="@id/music_control_background"
                />
        </Constraint>
        <Constraint
            android:id="@+id/music_button"
            >
            <PropertySet android:visibility="visible"/>
        </Constraint>
        <Constraint
            android:id="@+id/music_progress"
            >
            <Layout
                android:layout_width="400dp"
                android:layout_height="20dp"
                app:layout_constraintTop_toBottomOf="@+id/profile_photo"
                app:layout_constraintStart_toStartOf="@id/music_control_background"
                app:layout_constraintEnd_toEndOf="@id/music_control_background"
                android:layout_marginTop="50dp"
                />
            <PropertySet
                android:visibility="gone"
                />
        </Constraint>
        <Constraint
            android:id="@+id/close_button"
            >
            <Layout
                android:layout_width="80dp"
                android:layout_height="10dp"
                app:layout_constraintStart_toStartOf="@id/music_control_background"
                app:layout_constraintEnd_toEndOf="@id/music_control_background"
                app:layout_constraintTop_toTopOf="@id/music_control_background"
                android:layout_marginTop="15dp"
                />
            <PropertySet
                android:visibility="gone"
                />
        </Constraint>
    </ConstraintSet>



    <ConstraintSet
        android:id="@+id/end">
        <Constraint
            android:id="@+id/music_control_background"
            >
            <Layout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                />
        </Constraint>
        <Constraint
            android:id="@+id/profile_photo"
            >
            <Layout
                android:layout_width="200dp"
                android:layout_height="200dp"
                app:layout_constraintEnd_toEndOf="@id/music_control_background"
                app:layout_constraintStart_toStartOf="@id/music_control_background"
                app:layout_constraintTop_toTopOf="@id/music_control_background"
                android:layout_marginTop="120dp"
                />
        </Constraint>
        <Constraint
            android:id="@+id/music_button"
            >
            <PropertySet
                android:visibility="gone"
                />
        </Constraint>
        <Constraint
            android:id="@+id/music_progress"
            >
            <Layout
                android:layout_width="400dp"
                android:layout_height="20dp"
                app:layout_constraintTop_toBottomOf="@+id/profile_photo"
                app:layout_constraintStart_toStartOf="@id/music_control_background"
                app:layout_constraintEnd_toEndOf="@id/music_control_background"
                android:layout_marginTop="50dp"
                />
            <PropertySet
                android:visibility="visible"
                />
        </Constraint>
        <Constraint
            android:id="@+id/close_button"
            >
            <Layout
                android:layout_width="80dp"
                android:layout_height="10dp"
                app:layout_constraintStart_toStartOf="@id/music_control_background"
                app:layout_constraintEnd_toEndOf="@id/music_control_background"
                app:layout_constraintTop_toTopOf="@id/music_control_background"
                android:layout_marginTop="15dp"
                />
            <PropertySet
                android:visibility="visible"
                />
        </Constraint>
    </ConstraintSet>



    <Transition
        app:constraintSetStart="@+id/start"
        app:constraintSetEnd="@+id/end"
        >
        <OnSwipe
            app:touchAnchorId="@+id/profile_photo"
            app:dragDirection="dragUp"
            app:moveWhenScrollAtTop="true"
            app:nestedScrollFlags="disableScroll"
            app:maxAcceleration="1.5"
            app:maxVelocity="4"
            />
        <OnClick
            app:targetId="@+id/close_button"
            app:clickAction="toggle"
            />
        <KeyFrameSet>
            <KeyAttribute
                app:motionTarget="@+id/music_button"
                app:framePosition="20"
                android:alpha="0"
                >
            </KeyAttribute>
            <KeyPosition
                app:motionTarget="@+id/profile_photo"
                app:keyPositionType="deltaRelative"
                app:framePosition="20"
                app:sizePercent="1"
                app:percentX="1"
                app:percentY="0.2"
                />
            <KeyPosition
                app:motionTarget="@+id/music_control_background"
                app:keyPositionType="pathRelative"
                app:framePosition="30"
                app:percentHeight="0.5"
                app:percentX="0.5"/>
            <KeyPosition
                app:motionTarget="@+id/close_button"
                app:framePosition="30"
                app:sizePercent="1"
                app:keyPositionType="pathRelative"
                app:percentX="0.5"
                />
            <KeyAttribute
                app:motionTarget="@+id/close_button"
                app:framePosition="30"
                android:alpha="1"
                >
            </KeyAttribute>
        </KeyFrameSet>
    </Transition>

</MotionScene>

疑惑

moveWhenScrollAtTop=”true” + app:nestedScrollFlags=”disableScroll” 可以保证滑动正常

<OnSwipe
            app:touchAnchorId="@+id/profile_photo"
            app:dragDirection="dragUp"
            app:moveWhenScrollAtTop="true"
            app:nestedScrollFlags="disableScroll"
            app:maxAcceleration="1.5"
            app:maxVelocity="4"
            />

部分源码 (看的不是很懂

@Override
  public void onNestedPreScroll(@NonNull View target,
                                int dx,
                                int dy,
                                @NonNull int[] consumed,
                                int type) {

      MotionScene scene = mScene;
      if (scene == null) {
          return;
      }

      MotionScene.Transition currentTransition = scene.mCurrentTransition;
      if (currentTransition == null || !currentTransition.isEnabled()) {
          return;
      }

      if (currentTransition.isEnabled()) {
          TouchResponse touchResponse = currentTransition.getTouchResponse();
          if (touchResponse != null) {
              int regionId = touchResponse.getTouchRegionId();
              if (regionId != MotionScene.UNSET && target.getId() != regionId) {
                  return;
              }
          }
      }
      // 好像是在这里判断的 
      if (scene.getMoveWhenScrollAtTop()) {
          // This blocks transition during scrolling
          TouchResponse touchResponse = currentTransition.getTouchResponse();
          int vert = -1;
          if (touchResponse != null) {
              if ((touchResponse.getFlags() & TouchResponse.FLAG_SUPPORT_SCROLL_UP) != 0) {
                  vert = dy;
              }
          }
          if ((mTransitionPosition == 1 || mTransitionPosition == 0)
                  && target.canScrollVertically(vert)) {
              return;
          }
      }

      // This should be disabled in androidx
      if (currentTransition.getTouchResponse() != null
              && (currentTransition.getTouchResponse().getFlags()
              & TouchResponse.FLAG_DISABLE_POST_SCROLL) != 0) {
          float dir = scene.getProgressDirection(dx, dy);
          if ((mTransitionLastPosition <= 0.0f && (dir < 0))
                  || (mTransitionLastPosition >= 1.0f && (dir > 0))) {
              if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                  target.setNestedScrollingEnabled(false);
                  // TODO find a better hack
                  target.post(new Runnable() {
                      @Override
                      public void run() {
                          target.setNestedScrollingEnabled(true);
                      }
                  });
              }
              return;
          }
      }

      if (DEBUG) {
          Log.v(TAG, "********** onNestedPreScroll(target:"
                  + Debug.getName(target) + ", dx:" + dx + ", dy:" + dy + ", type:" + type);
      }
      float progress = mTransitionPosition;
      long time = getNanoTime();
      mScrollTargetDX = dx;
      mScrollTargetDY = dy;
      mScrollTargetDT = (float) ((time - mScrollTargetTime) * 1E-9);
      mScrollTargetTime = time;
      if (DEBUG) {
          Log.v(TAG, "********** dy = " + dx + " dy = " + dy + " dt = " + mScrollTargetDT);
      }
      scene.processScrollMove(dx, dy);
      if (progress != mTransitionPosition) {
          consumed[0] = dx;
          consumed[1] = dy;
      }
      evaluate(false);
      if (consumed[0] != 0 || consumed[1] != 0) {
          mUndergoingMotion = true;
      }

  }

Layout

<?xml version="1.0" encoding="utf-8"?>
<layout 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">

    <data>

    </data>

    <androidx.constraintlayout.motion.widget.MotionLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/teal_200"
        app:layoutDescription="@xml/motion"
        app:showPaths="true"
        tools:context=".MainActivity">


        <View
            android:id="@+id/bottom_navi"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:background="@color/black"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />

        <View
            android:id="@+id/music_control_background"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:background="@color/white"
            app:layout_constraintBottom_toTopOf="@id/bottom_navi"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />

        <ImageView
            android:id="@+id/profile_photo"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_marginStart="20dp"
            android:scaleType="centerCrop"
            android:src="@drawable/ic_toma"
            android:contentDescription="23"
            app:layout_constraintBottom_toBottomOf="@+id/music_control_background"
            app:layout_constraintStart_toStartOf="@id/music_control_background"
            app:layout_constraintTop_toTopOf="@id/music_control_background" />

        <Button
            android:id="@+id/music_button"
            android:layout_width="100dp"
            android:layout_height="40dp"
            android:layout_marginEnd="20dp"
            android:text="play"
            app:layout_constraintBottom_toBottomOf="@id/music_control_background"
            app:layout_constraintEnd_toEndOf="@id/music_control_background"
            app:layout_constraintTop_toTopOf="@id/music_control_background" />

        <ProgressBar
            android:id="@+id/music_progress"
            android:layout_width="400dp"
            android:layout_height="20dp"
            android:visibility="gone"
            android:layout_marginTop="50dp"
            style="@style/Widget.AppCompat.ProgressBar.Horizontal"
            app:layout_constraintTop_toBottomOf="@+id/profile_photo"
            app:layout_constraintStart_toStartOf="@id/profile_photo"
            app:layout_constraintEnd_toEndOf="@id/profile_photo"
            />
        <View
            android:id="@+id/close_button"
            android:layout_width="80dp"
            android:layout_height="10dp"
            android:background="@color/black"
            app:layout_constraintStart_toStartOf="@id/music_control_background"
            app:layout_constraintEnd_toEndOf="@id/music_control_background"
            app:layout_constraintTop_toTopOf="@id/music_control_background"
            android:layout_marginTop="15dp"
            android:visibility="gone"
            />
        <androidx.core.widget.NestedScrollView
            android:id="@+id/scroll_test"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toTopOf="@+id/music_control_background"
            >
            <LinearLayout
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:layout_height="match_parent">
                <View
                    android:layout_width="match_parent"
                    android:layout_height="100dp"
                    android:background="@color/black"
                    />
                <View
                    android:layout_width="match_parent"
                    android:layout_height="100dp"
                    android:background="@color/white"
                    />
                <View
                    android:layout_width="match_parent"
                    android:layout_height="100dp"
                    android:background="@color/black"
                    />
                <View
                    android:layout_width="match_parent"
                    android:layout_height="100dp"
                    android:background="@color/white"
                    />
                <View
                    android:layout_width="match_parent"
                    android:layout_height="100dp"
                    android:background="@color/black"
                    />
                <View
                    android:layout_width="match_parent"
                    android:layout_height="100dp"
                    android:background="@color/white"
                    />
                <View
                    android:layout_width="match_parent"
                    android:layout_height="100dp"
                    android:background="@color/black"
                    />
                <View
                    android:layout_width="match_parent"
                    android:layout_height="100dp"
                    android:background="@color/white"
                    /><View
                android:layout_width="match_parent"
                android:layout_height="100dp"
                android:background="@color/black"
                />
                <View
                    android:layout_width="match_parent"
                    android:layout_height="100dp"
                    android:background="@color/white"
                    />
                <View
                    android:layout_width="match_parent"
                    android:layout_height="100dp"
                    android:background="@color/black"
                    />
                <View
                    android:layout_width="match_parent"
                    android:layout_height="100dp"
                    android:background="@color/white"
                    />
                <View
                    android:layout_width="match_parent"
                    android:layout_height="100dp"
                    android:background="@color/black"
                    />
                <View
                    android:layout_width="match_parent"
                    android:layout_height="100dp"
                    android:background="@color/white"
                    />

            </LinearLayout>

        </androidx.core.widget.NestedScrollView>

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

文章作者: Lao Wu
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Lao Wu !
评论
  目录