美文网首页
ConstraintSet MotionLayout学习

ConstraintSet MotionLayout学习

作者: 有点健忘 | 来源:发表于2018-09-18 16:59 被阅读528次

    看这里学习的https://www.jianshu.com/p/54a6e2568cdd#comment-28749841
    顺道看下文档https://developer.android.com/reference/android/support/constraint/ConstraintSet

    ConstraintSet

    这东西就是一堆view的约束条件的集合
    实例化的方法

    //Manually 
    c = new ConstraintSet(); c.connect(....);
    //from a R.layout.* object 
    c.clone(context, R.layout.layout1);
    //看下这方法可以看到上边的layout1布局,根元素需要是ConstraintLayout
        public void clone(Context context, int constraintLayoutId) {
            this.clone((ConstraintLayout)LayoutInflater.from(context).inflate(constraintLayoutId, (ViewGroup)null));
        }
    //from a ConstraintLayout 
    c.clone(clayout);
    
    //还有这种弄一个布局的,当然了这个布局不要求根元素是ConstraintLayout
    constraintSet.load(this, R.layout.keyframe_two); 
    

    顺道简单看下这个几个方法的源码,可以看到这里的布局或者ConstraintLayout里的所有child都必须设置id


    image.png
    理解

    ConstraintSet 怎么说了,这东西可以理解成我们以前比如线性布局,相对布局的LayoutParams属性的集合。
    嗯嗯,我觉得是差不多。
    至于上边的clone,load其实都是从一个布局或者说从一个ConstraintLayout 里把所有的约束条件都提取出来而已。而且上边也说了里边的child必须要有个id,为啥了,是因为它要根据id和我们当前的布局对应起来。
    最后这个set的使用方法都是这样的
    constraintSet.applyTo(constraintLayout1)
    也就是说它把自己从其他地方提取的【clone,load方法等】约束条件,应用到一个老的constraintLayout1上边。

    constraintSet只能从布局提取吗?

    答案是否定的,看下这个类里边的方法,好多个。
    和普通的LayoutParams一样,它也可以手动设置一些属性的

    比如有个老的按钮,我们现在给它设置新的属性如下
    需要注意,新的属性,必须要保证这个view的具体位置,大小。也就是新的属性得保证这个view在某个位置。下边的,如果你不设置宽高,你会发现applyTo以后,按钮就不见了 。

    constraintSet.setMargin(R.id.btn_test,ConstraintSet.LEFT,100)
            constraintSet.setMargin(R.id.btn_test,ConstraintSet.TOP,200)
            constraintSet.constrainHeight(R.id.btn_test,200)
            constraintSet.constrainWidth(R.id.btn_test,100)
    

    比如 public void setGoneMargin(int viewId, int anchor, int value)
    我们在xml也可以设置这种属性 app:layout_goneMarginLeft="100dp"
    这个anchor的值有6种,LEFT,RIGHT,TOP,BOTTOM,START ,END
    方法是干啥的它就具体设置啥的,比如下边的设置goneMargin的


    image.png

    这个就是设置正常margin的


    image.png
    比如下边这些2个参数的,很多都是一个id,一个值,看名字也就大概知道干啥了,对应的都是xml的属性
    image.png
    我刚开始的疑问

    刚开始看到下边的代码,我还以为是替换布局了,还专门给老的布局的按钮弄个点击事件看有没有改变,后来发现自己想多了,看完上边分析,已经知道了,这里只是从这个布局或者说是constraintLayout里把每个child的约束属性读出来存起来而已,并不是替换这个布局。
    之后applyTo就是把set里的约束,根据id找到对应的,然后把约束应用到老的布局上而已。


    image.png

    MotionLayout

    public class MotionLayout extends ConstraintLayout implements NestedScrollingParent2
    子类而已,所以父类有的它都有,很明显实现了嵌套滚动
    文档 https://developer.android.com/reference/android/support/constraint/motion/MotionLayout

    implementation 'com.android.support.constraint:constraint-layout:2.0.0-alpha1'
    2.0以后的库才有这个东西,这玩意需要一个motionscene的文件来实现动画,最低要求版本是18,也就是这个库的minSdkVersion =18

    image.png

    大家先看下文章开头的帖子,看完基本入门了,完事再去看上边官方文档,看下各个属性的描述,也就理解的八九不离十了,之后就是自己在demo里测试了

    下边贴一个motionscene文件,这个文件是放在res的xml文件夹下边的,使用的时候是在布局文件里添加layoutDescription标签的,下图


    image.png

    回头再看,下边有图先整体分析下结构,跳到代码后边

    <?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
            android:id="@+id/my_transition"
            app:constraintSetEnd="@+id/ending_set"
            app:constraintSetStart="@+id/starting_set"
            app:duration="4000">
            <KeyFrameSet android:id="@+id/frameSet1">
                <KeyPosition
    
                    app:curveFit="arc"
    
                    app:drawPath="path"
                    app:framePosition="30"
                    app:percentX="0.85"
                    app:target="@+id/btn_test"
    
                    app:type="deltaRelative" />
                <KeyPosition
    
                    app:framePosition="60"
    
                    app:percentX="1"
    
                    app:target="@+id/btn_test"
    
                    app:type="deltaRelative" />
                <KeyCycle
    
                    android:rotation="50"
                    app:framePosition="50"
    
                    app:target="@+id/btn_test"
    
                    app:wavePeriod="1"
    
                    app:waveShape="square" />
            </KeyFrameSet>
            <OnClick
                app:mode="transitionToEnd"
                app:target="@+id/btn_test" />
            <OnSwipe app:dragDirection="dragDown"
                app:touchAnchorId="@+id/btn_test"
                app:touchAnchorSide="left"/>
        </Transition>
        
        <ConstraintSet android:id="@+id/starting_set">
            <Constraint
                android:id="@+id/btn_test"
                android:layout_width="160dp"
                android:layout_height="60dp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintRight_toRightOf="parent" />
        </ConstraintSet>
    
        <ConstraintSet android:id="@+id/ending_set">
            <Constraint
                android:id="@+id/btn_test"
                android:layout_width="160dp"
                android:layout_height="60dp"
                android:layout_marginTop="100dp"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent" />
        </ConstraintSet>
    
    </MotionScene>
    
    image.png

    MotionScene下有3种节点,StateSet试了下没反应,不管它了先


    image.png
    ConstraintSet

    一般这玩意有两个对应上边的Transition标签
    每个ConstraintSet里边就是N个Constraint标签了,用来处理想要进行动画的view的位置的。这里的id和我们布局里的id一样的,你想哪个动,就在这里处理他们的位置。

    Transition

    下边2个属性,一个是动画起始的时候的约束set,一个是结束的时候的约束set,指向上边介绍的ConstraintSet

    constraintSetStart ConstraintSet to be used as the start constraints or a layout file to get the constraint from
    constraintSetEnd ConstraintSet to be used as the end constraints or a layout file to get the constraint from

    OnSwipe (optional)

    处理触摸事件的
    dragDirection》》which side to swipe from {dragUp|dragDown|dragLeft|dragRight}
    touchAnchorId 》》Have the drag act as if it is moving the "touchAnchorSide" of this object
    dragDirection 就是手指滑动的方向了,左右,上下 触发动画事件,拖动到一半松手,动画自动就还原了。
    touchAnchorId 这个东西好像是那个在进行动画的view的id。

    OnClick (optional)

    target》》》What button triggers Transition.
    mode》》》Direction for buttons to move the animation. mode: transitionToEnd, toggle, transitionToStart, jumpToEnd, jumpToStart
    这个就2个属性,target 指向一个view的id,指定点击哪个view触发事件
    第二个就是mode了,有5种 transitionToEnd, toggle, transitionToStart, jumpToEnd, jumpToStart
    就是前边Transition里的constraintSetStart和constraintSetEnd 决定从start到end还是end到start
    注意
    jumpToEnd, jumpToStart这两个先别用,看字面意思我以为直接结束动画了,可实际运行了下直接挂了。报的空指针,ConstraintLayout$States为空。也不知道是不是和前边忽略的标签StateSet有关,先放下

    KeyFrameSet关键帧的集合

    前边一堆,我们也看到我们的动画只有开头和结束两种状态,中间其实就是线性的对x和y的位置进行过渡的。
    比如view开始在左上角,结束在右下角,那么正常动画就是斜线了。
    如果我们需要view拐个弯啥的,咋办了。KeyFrameSet就是干这个用的,可以插入一些中间帧。


    image.png

    研究下简单的两种

    KeyPosition

    target Id of the View
    framePosition The point along the interpolation 0 = start 100 = end
    percentX (float) percent distance from start to end along X axis (deltaRelative) or along the path in pathRelative
    percentY (float) Percent distance from start to end along Y axis (deltaRelative) or perpendicular to path in pathRelative
    sizePercent If the view changes size this controls how growth of the size. (for fixed size objects use KeyAttributes scaleX/X)
    target 指定是哪个view没啥说的,因为动画过程可能有N个在发生变化,总得说下这个是给谁的
    framePosition 这个就是动画运行时间的百分比,从0到100的时间段,指定啥时候到这个position
    percentX 指定在framePostion这个时间点的时候x应该在啥位置,这个是个百分比,0到1之间的值。就是最终的x和开始的x之间的百分比。
    percentY一个道理
    sizePercent 这个和上边x,y其实一样,不过这里是对大小改变的view来说的。

    KeyCycle

    image.png

    app:wavePeriod 这个就是波形的次数,比如正弦从0到360是一次,你要执行2次,这里就写个2
    app:framePosition 和上边一样,指定一个时间点,在这个附近应用Cycle
    android:rotation="50" 下边列子是一个角度旋转的动画,这里指定50,就是最大值了。
    实际的动画受到波形的影响。比如波形是正弦,那么正弦的值从0到1到0再到-1最后又到0
    那么实际的角度 就是不停的变化了,就是那个50度乘以这个正弦值。
    其他的波形逻辑是一样的,不过那些波形的值的变化没研究,不太清楚。
    举例如下

                <KeyCycle
                    app:target="@+id/btn_test"
                    android:rotation="50"
                    app:framePosition="50"
                    app:wavePeriod="1"
                    app:waveShape="sin" />
    

    下边是支持的标准属性,用这些属性,加上波形,就可以让控件忽明忽暗,一会变大一会缩小,旋转了。看自己需求了。。。


    image.png

    相关文章

      网友评论

          本文标题:ConstraintSet MotionLayout学习

          本文链接:https://www.haomeiwen.com/subject/oscynftx.html