源码在这里
:
源码链接
本文是用java写的
下面是本博客我使用真机所实现的功能展现,方便大家根据自身需求自取
想要实现MotionLayout
,第一步就是使用ConstraintLayout
布局,然后将其一键转换,就可以得到MotionLaout
布局和其对应的scene
文件
点击下图的Convert to MotionLayout
就可以得到一个MotionLayout
布局,
这里注意了,原先的ConstrainLayout布局中的组件的顺序是有意义的,在后续scene
的文件中是根据这里面的顺序进行排布的。
转换完成后,你就会得到一个这样的MotionLayout
布局的activity_main.xml
以及一个大致长这样的activity_main_scene.xml
首先将你所要放入的组件先放入到你的MotionLaout
中,下面是我的主页面的MotionLayout
中的内容
这边给大家解释一下下面用到的几个组件的含义
Guideline
这个东西你可以理解为是一个用来确定组件位置的辅助线,你可以在编辑界面中看到这些辅助线,但是当你运行它时,却不会显示,方便咱定位组件位置, android:orientation="vertical"
表明这是一条垂直的辅助线app:layout_constraintGuide_percent="0.2"
表明它所处的位置大概是在20%的位置Guideline
ImageFilterView
这个组件可以便于后续实现轮播图中在灰度级的控制(即将图片的变成黑白效果,这是普通的ImageView
所做不到的,如果你不想实现这个灰度级的控制,就可以使用普通的ImageView
)Carousel
这个玩意是用来实现轮播图的,试想,正常情况下,你将轮播图向左拖动到下一个页面时,这个动画按理说已经结束了,没法继续切换图片了,那咋办呢,就是用的这个玩意,这里就先不细讲了哈废话结束,现在开始动画的制作
Create Constraint
,你就可以开始做动画的效果啦,这里的start
,指的是开始时的状态,一般你创建MotionLayout
中,除了start
,还会预先给你创建一个end
,这个是结束时的状态,将这两个状态设置完毕后,它就会自动的给你生成动画效果,当然,你可以进行自定义start
状态进行实现,你可以用右边的Attributes
来实现,就像上面那张图那样,也可以手动在scene
里面写
ConstraintSet
部分: ConstraintSet
就是几个状态,start
就是开始阶段的状态,previous
是切换到上一页时的状态,next
是切换到下一页的状态,big是把图片放大时的状态scaleX、scaleY
是对应方向上面的缩放attributeName="Saturation"
这玩意就是上面说到的灰度级的实现了,当值为0时,为黑白图rotationY
是图片的绕Y轴旋转,如下图中左边和右边的两张图片translationZ
是图片的Z轴高度,看下面这张3D效果图就很好理解了(如果你也想看到这种效果的话,可以点击你的AS中的tools
,选择Layout Inspector
,然后点击右下角我用红笔圈中的部分,就可以切换3D效果)
motion:constraintSetStart
就是状态衔接中的起始状态motion:constraintSetEnd
就是状态衔接中的结束状态duration
就是这个衔接过程的时间,我是这么理解的,但是实际实现起来,有的时候却不会按照这个时间,但是总体影响不大Onswipe
就是滑动效果,上面这个代码中,touchRegionId
就是你拖动的组件,dragDirection
就是你滑动的方向,上面的代码片段即:当你左滑id=img3
的组件时,会实现从start
状态到next
状态的转换Carousel
终于到了这个部分,完成了这个部分后,就可以实现轮播图的切换了
首先,我们来看一看官方文档中的介绍:具体请看官方文档: https://developer.android.google.cn/develop/ui/views/animations/motionlayout/carousel
带运动布局的旋转木马
Carousel是一个运动辅助对象,可以轻松构建自定义的“carousel”视图,显示用户可以浏览的元素列表。与实现这种视图的其他解决方案相比,该助手允许您通过利用MotionLayout.
Carousel小部件支持带有开始和结束的列表以及循环环绕列表。
概念:如何旋转木马MotionLayout作品
假设我们想要构建一个简单的水平旋转视图,并放大居中的视图:
我们的基本布局包含几个视图,代表我们的轮播项目:
创建一个MotionLayout有三种状态(确保给他们id):
以前的
开始
然后
如果开始状态对应于基础布局,则以前的状态应该以这样一种方式完成,即轮播项目将移动一个。
例如,假设我们有5个视图:A、B、C、D、E处于开始状态,B、C、D可见,A和E在屏幕之外。我们想建立一个以前的陈述A、B、C、D的位置现在是B、C、D、E所在的位置,视图从左向右移动。在……里然后状态,需要发生相反的情况,B,C,D,E移动到A,B,C,D所在的位置,视图从右向左移动。
重要的是视图正好在原始视图开始的地方结束;旋转木马给人一种无限元素集合的错觉的方式是通过移动实际的视图恢复到原来的位置,但是用新的匹配内容重新初始化它们。下图显示了这种机制(注意“项目#”值):
好了,上面的就是官方文档的内容,相信看了这部分之后你应该就对Carousel
是干嘛的有了一个初步的想法,说了这么多,那么要如何通过java代码来实现呢,请继续看后续的部分:
Carousel
,以便后续在java代码中进行调用,还是老样子,先上代码:
开始解析:
carousel_forwardTransition
向前跳转的动画
carousel_backwardTransition
向后跳转的动画
carousel_previousState
向前跳转动画完成后对应的状态
carousel_nextState
:向后跳转动画后对应的状态
carousel_infinite
:开启无限循环
carousel_firstView
:老实讲,没太懂,反正放第一个图的id就完事
package com.example.forblog;import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.helper.widget.Carousel;import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;import kotlin.jvm.JvmOverloads;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);int images[] = {R.drawable.img1,R.drawable.img2,R.drawable.img3,R.drawable.img4};Carousel carousel = findViewById(R.id.carousel);carousel.setAdapter(new Carousel.Adapter() {@Overridepublic int count() {// need to return the number of items we have in the carouselreturn 4;}@Overridepublic void populate(View view, int index) {if (view instanceof ImageView){((ImageView) view).setImageResource(images[index]);}// need to implement this to populate the view at the given index}@Overridepublic void onNewItem(int index) {// called when an item is set}});}
}
count
函数里面返回图片总数populate
函数里面:需要实现这一点以填充给定索引处的视图(我只是简单的拿过来用,其实这个我没有太理解,但是能模仿着用就成)当你做到这里,你就可以运行你的程序了,一个完整的轮播图效果就实现了!!!
当你看完了上面轮播图的实现后,其实想要完成一个启动页的模拟效果,已经很接近啦,只要做一个动画效果,然后让其自动播放,然后在几秒后自动跳转到MainActivity页面就行了
我这里其实就是使用投机的方式,在网上找了一个自动点击页面的代码(设置动画为点击页面后开始),然后在启动页放一个线程,睡眠一段时间后跳转页面就行
详细请见源码https://github.com/lrhzds/MotionLayout_Demo
上面的activity_start_scene.xml
的部分代码中定义一个点击事件
java代码如下,实例化了一个单击事件AutoTouch(),当页面加载时,会启动一个线程,先睡眠6秒(这段时间其实就是启动页动画的时间),6秒后会自动跳转到主界面,这样就能完成一个伪启动页
的效果
public class AutoTouch {public void autoClickPos(final double x1, final double y1, final double x2, final double y2) {new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(500);} catch (Exception e) {e.printStackTrace();}System.out.println("=========");String[] order = {"input", "swipe", "" + x1, "" + y1, "" + x2, "" + y2,};try {new ProcessBuilder(order).start();} catch (Exception e) {e.printStackTrace();}}}).start();}
setContentView(R.layout.activity_start);AutoTouch autoTouch = new AutoTouch();autoTouch.autoClickPos(300,300,300,300);Thread t= new Thread(new Runnable() {@Overridepublic void run() {//1:休眠6Stry {Thread.sleep(6000);} catch (InterruptedException e) {e.printStackTrace();}//进入主页面Intent it=new Intent(StartActivity.this,MainActivity.class);startActivity(it);}});//2:启动这个子线程t.start();
如果对上面的gif图的插入有兴趣的话可以继续看后续的内容,如果没有那本篇博客的内容就到此结束啦,感谢您的观看!!!
//GIFimplementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.15'
只要导入上面的库,然后在activity里面直接使用就行
官方文档
参考链接
作者:林睿航
原文链接