MotionLayoutã§ã¢ãã¡ã¼ã·ã§ã³ä½ã
ãã®è¨äºã¯ Android Advent Calendar 2018 ã®5æ¥ç®ï¼ã®ä»£æï¼ã§ãã
ã ãããããèªãã°åºæ¬ã¯ä¸éãããã
ãµã³ãã«ã¯ãã®Repositoryã®ä¸ã®motionlayoutãã£ã¬ã¯ããªããã«ãããã°è©¦ãã github.com
éãªæ¦è¦
- MotionLayoutã¯ConstraintLayout 2.0ã«å«ã¾ãã¦ãããConstraintLayoutã®ããã±ã¼ã¸ã«å«ã¾ãã¦ããã®ã¯MotionLayoutãConstraintLayoutã®ãµãã¯ã©ã¹ã«ãªã£ã¦ããããã
- ãªãã¸ã§ã¯ãã®ã¢ã¼ã·ã§ã³éå§ç¶æ ã¨çµäºç¶æ ã®Constraintãå®ç¾©ãã¦ãã¢ã¼ã·ã§ã³ã¹ã¿ã¼ããããã¨éå§ç¶æ ããçµäºç¶æ ã¾ã§ãªãã¸ã§ã¯ããå¤åãããåã«éå§ã»çµäºãæå®ããã ãã ã¨ã·ã³ãã«ã«å¤åããã ãã ããKeyFrameSetãCustomAttributeã使ããã¨ã§ãå¤æ§ãªå¤åãå®ç¾©ã§ããã
- åºæ¬ã®è¨å®
- MotionLayoutå ã«åãããããªãã¸ã§ã¯ããé ç½®ãããåãããããªãã¸ã§ã¯ã以å¤ã¯é ç½®ããªãã
- ãªãã¸ã§ã¯ãã®ã¢ã¼ã·ã§ã³ã®éå§ç¶æ ã¨çµäºç¶æ ãå®ç¾©ããSceneãä½æããã
- Transitionãè¨å®ããéå§ç¶æ ã¨çµäºç¶æ ãè¨å®ãããå¿ è¦ãªãã¢ã¼ã·ã§ã³éå§ã®ãã³ãã©ãè¨å®ããï¼ã¯ãªãã¯ãã¹ã¯ã¤ããªã©ï¼ãè¨å®ããªãã¦ãä»ã®ViewããMotionLayoutã®progressããããã£ãæä½ãããã¨ã§ã¢ã¼ã·ã§ã³ãã³ã³ããã¼ã«ã§ããã
- ä½æããã·ã¼ã³ãMotionLayoutã«è¨å®ãã
åºæ¬ã®ãµã³ãã«ï¼åé ã®android-ConstraintLayoutExamplesããï¼
- scene.xml
<?xml version="1.0" encoding="utf-8"?> <MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:motion="http://schemas.android.com/apk/res-auto"> <Transition motion:constraintSetEnd="@+id/end" motion:constraintSetStart="@+id/start"> <OnSwipe motion:dragDirection="dragRight" motion:touchAnchorId="@+id/button" motion:touchAnchorSide="right" /> </Transition> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginStart="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginEnd="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintEnd_toEndOf="parent" motion:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> </MotionScene>
- scene_fragment.xml
<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/motionLayout" app:layoutDescription="@xml/scene" // ä½æããSceneãæå® app:showPaths="true" android:background="@android:color/white" android:layout_width="match_parent" android:layout_height="match_parent"> <View android:id="@+id/button" android:background="@color/colorAccent" android:layout_width="64dp" android:layout_height="64dp" android:text="Button" /> </androidx.constraintlayout.motion.widget.MotionLayout>
- ããã§æ³¨æãããã¤ã³ãã¯ã¢ã¼ã·ã§ã³ã®å¯¾è±¡ã¨ãªããªãã¸ã§ã¯ãï¼id/buttonï¼ã®MotionLayoutå ã§è¨å®ããconstraintã¯ç¡è¦ããã¦ãSceneã®éå§ç¶æ ã®constraintãåªå ãããã
- åããã¨âã®ããã«ãªããMotionLayoutãã¹ã¯ã¤ãããã¨å¯¾è±¡ã®ãªãã¸ã§ã¯ãã移åãã¦ããã®ããããã
KeyFrame
- KeyFrameã使ãã¨éå§ã»çµäºã®ä¸éã®ç¶æ ãå®ç¾©ã§ãããä¸ã®ãµã³ãã«ã®Transitionã®ä¸ã«ä»¥ä¸ã®ãããªKeyFrameã追å ãã¦ã¿ãã
<Transition motion:constraintSetEnd="@+id/end" motion:constraintSetStart="@+id/start"> <OnSwipe motion:dragDirection="dragRight" motion:touchAnchorId="@+id/button" motion:touchAnchorSide="right" /> <KeyFrameSet> <KeyPosition motion:framePosition="33" motion:keyPositionType="pathRelative" motion:percentY="-0.3" motion:target="@id/button" /> <KeyPosition motion:framePosition="66" motion:keyPositionType="pathRelative" motion:percentY="0.3" motion:target="@id/button" /> </KeyFrameSet> </Transition>
- framePositonã¯éå§ã0ã§çµäºã100ã«ãªããKeyFrameã¯ãã®ä¸éã®å¤ã®æã«ã©ã®ãããªç¶æ ã«ãªãããæå®ãããä¸è¨ã®ä¾ã¯positonã33ã66ã®æã«y座æ¨ã®ä½ç½®ãå¤ãããããªæå®ã«ãªã£ã¦ããã
- KeyFrameã¯ä»¥ä¸ã®ç¨®é¡ãæå®ã§ãã
- KeyPosition: 座æ¨ãå¤åã§ãã
- KeyAttribute: å±æ§ãå¤åã§ãã
- KeyCycle: å±æ§ã®å¤åãç¹°ãè¿ã
CustomAttributeã使ã£ã¦ãªãã¸ã§ã¯ãã®å±æ§ãå¤åãã
- KeyAttributeã§æå®ã§ããªãå±æ§ãCustomAttributeã使ãã°ç¶æ ãå¤åã§ãããå±æ§åã¯ãªãã¸ã§ã¯ãã«çãã¦ããgetter/setterããget/setãé¤ããååãæå®ããã
- CustomAttributeã¯Constraintã¨KeyAttributeã®åè¦ç´ ã«æå®ã§ãããåºæ¬ã®ãµã³ãã«ã以ä¸ã®ããã«å¤æ´ãã¦ã¿ãã
<?xml version="1.0" encoding="utf-8"?> <MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:motion="http://schemas.android.com/apk/res-auto"> <Transition motion:constraintSetEnd="@+id/end" motion:constraintSetStart="@+id/start"> <OnSwipe motion:dragDirection="dragRight" motion:touchAnchorId="@+id/button" motion:touchAnchorSide="right" /> <KeyFrameSet> <KeyAttribute motion:framePosition="50" android:scaleX="2" android:scaleY="2" motion:target="@+id/button"> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="@color/colorPrimaryDark" /> </KeyAttribute> </KeyFrameSet> </Transition> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginStart="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent"> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="@color/colorAccent" /> </Constraint> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginEnd="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintEnd_toEndOf="parent" motion:layout_constraintTop_toTopOf="parent"> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="@color/colorAccent" /> </Constraint> </ConstraintSet> </MotionScene>
- éå§ã»çµäºã®Constraintã«åæ表示æã®backgroundColorã追å ãframePosition=50ã®æç¹ã®KeyAttributeã追å ãã¦ãåæ表示ã¨ç°ãªãbackgroundColorã追å ããããããåããã¨ä»¥ä¸ã®ããã«ãªãã
æ¢åã®Componentã¨MotionLayoutãé£æºãã
- MotionLayoutã®progressããããã£ãæä½ããã°OnClickãOnSwipeãè¨å®ããªãã¦ããªãã¸ã§ã¯ããå¤åããããã¨ãã§ããã試ãã«Buttonãæ¼ããã10é²ãããã«ãã¦ã¿ãã
- ã³ã¼ãã¯ä»¥ä¸ã®ããã«ãªã£ã¦ãããMotionLayoutã®progressãããã£ã¦ããã ãã
val motionLayout = view.findViewById<MotionLayout>(R.id.motionLayout) val button = view.findViewById<Button>(R.id.go) button.setOnClickListener { val current = motionLayout.progress val next = current + 0.1f motionLayout.progress = if (next > 1) 0f else next }
- ConstraintLayoutExamplesã«ã¯DrawerãCoordinatorLayoutã¨é£æºãããµã³ãã«ãè¼ã£ã¦ããã®ã§è©¦ãã¦ã¿ã¦ã»ããã
ããã¾ã
- Exampleã®ããã¸ã§ã¯ããããªãå å®ãã¦ããã®ã§ãããããã£ãã§ã ð