使用MotionLayout实现模拟启动页动画和轮播图

news2024/11/17 4:29:04

目录

  • 效果图展示
    • 启动页效果
    • 轮播图效果
  • MotionLayout详解
    • 准备工作
    • 正题
    • 轮播图效果实现
      • ConstraintSet
      • Transition
      • Carousel
    • 浅述启动页的实现
  • 插入gif图

源码在这里: 源码链接
本文是用java写的

效果图展示

下面是本博客我使用真机所实现的功能展现,方便大家根据自身需求自取

启动页效果

请添加图片描述

轮播图效果

请添加图片描述

MotionLayout详解

准备工作

想要实现MotionLayout,第一步就是使用ConstraintLayout布局,然后将其一键转换,就可以得到MotionLaout布局和其对应的scene文件
在这里插入图片描述

点击下图的Convert to MotionLayout就可以得到一个MotionLayout布局,
这里注意了,原先的ConstrainLayout布局中的组件的顺序是有意义的,在后续scene的文件中是根据这里面的顺序进行排布的。
在这里插入图片描述
转换完成后,你就会得到一个这样的MotionLayout布局的activity_main.xml
在这里插入图片描述
以及一个大致长这样的activity_main_scene.xml
在这里插入图片描述

正题

首先将你所要放入的组件先放入到你的MotionLaout中,下面是我的主页面的MotionLayout中的内容

<?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:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layoutDescription="@xml/activity_main_scene">

    <pl.droidsonroids.gif.GifImageView
        android:id="@+id/gifImv1"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_weight="1"
        android:scaleType="fitXY"
        android:src="@drawable/d320c53c8d16cda0b7431627e897d2b2"
        app:layout_constraintBottom_toBottomOf="@id/g7"
        app:layout_constraintLeft_toLeftOf="@id/g3"
        app:layout_constraintRight_toRightOf="@id/g4"
        app:layout_constraintTop_toTopOf="@id/g7" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/g1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.2" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/g2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.4" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/g3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.6" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/g4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.8" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/g5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.5" />



    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/g6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="1" />
    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/g7"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.8"/>
    <androidx.constraintlayout.utils.widget.ImageFilterView
        android:id="@+id/img1"
        android:layout_width="10dp"
        android:layout_height="10dp"
        android:src="@drawable/img1"
        android:visibility="invisible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.constraintlayout.utils.widget.ImageFilterView
        android:id="@+id/img2"
        android:layout_width="10dp"
        android:layout_height="10dp"
        android:src="@drawable/img2"
        android:visibility="invisible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.constraintlayout.utils.widget.ImageFilterView
        android:id="@+id/img3"
        android:layout_width="10dp"
        android:layout_height="10dp"
        android:src="@drawable/img3"
        android:visibility="invisible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.constraintlayout.utils.widget.ImageFilterView
        android:id="@+id/img4"
        android:layout_width="10dp"
        android:layout_height="10dp"
        android:src="@drawable/img4"
        android:visibility="invisible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
        
	<androidx.constraintlayout.helper.widget.Carousel
        android:id="@+id/carousel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:carousel_backwardTransition="@+id/backward"
        app:carousel_firstView="@+id/img1"
        app:carousel_forwardTransition="@+id/forward"
        app:carousel_infinite="true"
        app:carousel_nextState="@+id/next"
        app:carousel_previousState="@+id/previous"
        app:constraint_referenced_ids="img1,img2,img3,img4" />

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

这边给大家解释一下下面用到的几个组件的含义

  • Guideline这个东西你可以理解为是一个用来确定组件位置的辅助线,你可以在编辑界面中看到这些辅助线,但是当你运行它时,却不会显示,方便咱定位组件位置,
    • android:orientation="vertical"表明这是一条垂直的辅助线
    • app:layout_constraintGuide_percent="0.2"表明它所处的位置大概是在20%的位置
      下图中你所看到的虚线就是Guideline
      在这里插入图片描述
  • ImageFilterView这个组件可以便于后续实现轮播图中在灰度级的控制(即将图片的变成黑白效果,这是普通的ImageView所做不到的,如果你不想实现这个灰度级的控制,就可以使用普通的ImageView
  • Carousel这个玩意是用来实现轮播图的,试想,正常情况下,你将轮播图向左拖动到下一个页面时,这个动画按理说已经结束了,没法继续切换图片了,那咋办呢,就是用的这个玩意,这里就先不细讲了哈

轮播图效果实现

废话结束,现在开始动画的制作

  1. 首先,请点开你的design页面,这和平常的布局的design页面还是有较大区别的(个人觉得),长这样(这是我已经实现后的样子)
    在这里插入图片描述
  2. 点击中间的框中间的start,然后再点击中间下面的组件,然后点那根笔,选择Create Constraint,你就可以开始做动画的效果啦,这里的start,指的是开始时的状态,一般你创建MotionLayout中,除了start,还会预先给你创建一个end,这个是结束时的状态,将这两个状态设置完毕后,它就会自动的给你生成动画效果,当然,你可以进行自定义
  3. 那么,现在先开始对start状态进行实现,你可以用右边的Attributes来实现,就像上面那张图那样,也可以手动在scene里面写
  4. 那么,上代码:
	<?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
        android:id="@+id/forward"
        motion:constraintSetEnd="@id/next"
        motion:constraintSetStart="@id/start"
        motion:duration="1000">
        <OnSwipe
            motion:touchRegionId="@id/img3"
            motion:dragDirection="dragLeft"
            motion:touchAnchorSide="left" />
    </Transition>

    <Transition
        android:id="@+id/backward"
        motion:constraintSetEnd="@id/previous"
        motion:constraintSetStart="@id/start"
        motion:duration="1000">
        <OnSwipe
            motion:dragDirection="dragRight"
            motion:touchAnchorSide="right" />
    </Transition>

    <Transition
        android:id="@+id/changeBig"
        motion:constraintSetEnd="@id/big"
        motion:constraintSetStart="@id/start"
        motion:duration="1000">
        <OnSwipe
            motion:dragDirection="dragUp"
            motion:touchAnchorSide="top"/>
    </Transition>
    <ConstraintSet android:id="@+id/big">
        <Constraint
            android:id="@id/img3"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:adjustViewBounds="true"
            android:translationZ="100dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintRight_toRightOf="parent"
            motion:layout_constraintTop_toTopOf="parent" />
    </ConstraintSet>

    <ConstraintSet android:id="@+id/previous">
        <Constraint
            android:id="@id/img4"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:translationZ="0dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintDimensionRatio="2:1"
            motion:layout_constraintLeft_toLeftOf="@+id/g1"
            motion:layout_constraintRight_toRightOf="@id/g4"
            motion:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                motion:attributeName="Saturation"
                motion:customFloatValue="1.0"
                />
        </Constraint>

        <Constraint
            android:id="@id/img1"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:rotationY="30"
            android:scaleX="0.8"
            android:scaleY="0.8"
            android:translationZ="4dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintDimensionRatio="2:1"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintRight_toRightOf="@id/g3"
            motion:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                motion:attributeName="Saturation"
                motion:customFloatValue="0.0"
                />
        </Constraint>

        <Constraint
            android:id="@id/img2"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:scaleX="1.2"
            android:scaleY="1.2"
            android:translationZ="10dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintDimensionRatio="2:1"
            motion:layout_constraintLeft_toLeftOf="@+id/g1"
            motion:layout_constraintRight_toRightOf="@id/g4"
            motion:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                motion:attributeName="Saturation"
                motion:customFloatValue="1.0"
                />
        </Constraint>
        <Constraint
            android:id="@id/img3"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:rotationY="-30"
            android:scaleX="0.8"
            android:scaleY="0.8"
            android:translationZ="4dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintDimensionRatio="2:1"
            motion:layout_constraintLeft_toLeftOf="@id/g2"
            motion:layout_constraintRight_toRightOf="parent"
            motion:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                motion:attributeName="Saturation"
                motion:customFloatValue="0.0"
                />
        </Constraint>
    </ConstraintSet>

    <ConstraintSet android:id="@+id/start">
        <Constraint
            android:id="@id/img1"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:translationZ="0dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintDimensionRatio="2:1"
            motion:layout_constraintLeft_toLeftOf="@+id/g1"
            motion:layout_constraintRight_toRightOf="@id/g4"
            motion:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                motion:attributeName="Saturation"
                motion:customFloatValue="1.0"
                />
        </Constraint>

        <Constraint
            android:id="@id/img2"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:rotationY="30"
            android:scaleX="0.8"
            android:scaleY="0.8"
            android:translationZ="4dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintDimensionRatio="2:1"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintRight_toRightOf="@id/g3"
            motion:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                motion:attributeName="Saturation"
                motion:customFloatValue="0.0"
                />
        </Constraint>

        <Constraint
            android:id="@id/img3"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:scaleX="1.2"
            android:scaleY="1.2"
            android:translationZ="10dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintDimensionRatio="2:1"
            motion:layout_constraintLeft_toLeftOf="@+id/g1"
            motion:layout_constraintRight_toRightOf="@id/g4"
            motion:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                motion:attributeName="Saturation"
                motion:customFloatValue="1.0"
                />
        </Constraint>

        <Constraint
            android:id="@id/img4"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:rotationY="-30"
            android:scaleX="0.8"
            android:scaleY="0.8"
            android:translationZ="4dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintDimensionRatio="2:1"
            motion:layout_constraintLeft_toLeftOf="@id/g2"
            motion:layout_constraintRight_toRightOf="parent"
            motion:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                motion:attributeName="Saturation"
                motion:customFloatValue="0.0"
                />
        </Constraint>
    </ConstraintSet>
    <ConstraintSet android:id="@+id/next">
        <Constraint
            android:id="@id/img1"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:rotationY="-30"
            android:scaleX="0.8"
            android:scaleY="0.8"
            android:translationZ="6dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintDimensionRatio="2:1"
            motion:layout_constraintLeft_toLeftOf="@id/g2"
            motion:layout_constraintRight_toRightOf="parent"
            motion:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                motion:attributeName="Saturation"
                motion:customFloatValue="0.0"
                />
        </Constraint>
        <Constraint
            android:id="@id/img2"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:translationZ="0dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintDimensionRatio="2:1"
            motion:layout_constraintLeft_toLeftOf="@+id/g1"
            motion:layout_constraintRight_toRightOf="@id/g4"
            motion:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                motion:attributeName="Saturation"
                motion:customFloatValue="1.0"
                />
        </Constraint>

        <Constraint
            android:id="@id/img3"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:rotationY="30"
            android:scaleX="0.8"
            android:scaleY="0.8"
            android:translationZ="4dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintDimensionRatio="2:1"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintRight_toRightOf="@id/g3"
            motion:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                motion:attributeName="Saturation"
                motion:customFloatValue="0.0"
                />
        </Constraint>

        <Constraint
            android:id="@id/img4"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:scaleX="1.2"
            android:scaleY="1.2"
            android:translationZ="10dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintDimensionRatio="2:1"
            motion:layout_constraintLeft_toLeftOf="@+id/g1"
            motion:layout_constraintRight_toRightOf="@id/g4"
            motion:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                motion:attributeName="Saturation"
                motion:customFloatValue="1.0"
                />
        </Constraint>
    </ConstraintSet>
</MotionScene>

ConstraintSet

  • 现在来分析一下上面的代码中ConstraintSet部分:
    • 上面的ConstraintSet就是几个状态,start就是开始阶段的状态,previous是切换到上一页时的状态,next是切换到下一页的状态,big是把图片放大时的状态
  • 接着,来分析一下里面的代码,
    • scaleX、scaleY是对应方向上面的缩放
    • attributeName="Saturation"这玩意就是上面说到的灰度级的实现了,当值为0时,为黑白图
    • rotationY是图片的绕Y轴旋转,如下图中左边和右边的两张图片
      在这里插入图片描述
    • translationZ是图片的Z轴高度,看下面这张3D效果图就很好理解了(如果你也想看到这种效果的话,可以点击你的AS中的tools,选择Layout Inspector,然后点击右下角我用红笔圈中的部分,就可以切换3D效果)
      在这里插入图片描述

Transition

  • 这一部分在我看来就是实现几个状态的衔接,如:
    <Transition
        android:id="@+id/forward"
        motion:constraintSetEnd="@id/next"
        motion:constraintSetStart="@id/start"
        motion:duration="1000">
        <OnSwipe
            motion:touchRegionId="@id/img3"
            motion:dragDirection="dragLeft"
            motion:touchAnchorSide="left" />
    </Transition>
    
  • 以上面的这一部分来进行解析
    • motion:constraintSetStart就是状态衔接中的起始状态
    • motion:constraintSetEnd就是状态衔接中的结束状态
    • duration就是这个衔接过程的时间,我是这么理解的,但是实际实现起来,有的时候却不会按照这个时间,但是总体影响不大
    • 然后Onswipe就是滑动效果,上面这个代码中,touchRegionId就是你拖动的组件,dragDirection就是你滑动的方向,上面的代码片段即:当你左滑id=img3的组件时,会实现从start状态到next状态的转换
  • 当你完成了上面的那些部分时,你就已经完成了一个简单的轮播图的效果,你可以从展示第一张图片转换到第二张图片,但是当你进入这个状态时,要再切换到第三张图片,你会发现是做不到的,因为到目前为止还尚未实现这种效果,这时候,想要完成一个完美的轮播图效果,就要用到一个新的东西:Carousel

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代码来实现呢,请继续看后续的部分:

  • 首先,我们要再MotionLayout中插入Carousel,以便后续在java代码中进行调用,还是老样子,先上代码:
<androidx.constraintlayout.helper.widget.Carousel
        android:id="@+id/carousel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:carousel_backwardTransition="@+id/backward"
        app:carousel_firstView="@+id/img1"
        app:carousel_forwardTransition="@+id/forward"
        app:carousel_infinite="true"
        app:carousel_nextState="@+id/next"
        app:carousel_previousState="@+id/previous"
        app:constraint_referenced_ids="img1,img2,img3,img4" />

开始解析:

  • 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 {


    @Override
    protected 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() {
            @Override
            public int count() {
                // need to return the number of items we have in the carousel
                return 4;
            }

            @Override
            public 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
            }

            @Override
            public void onNewItem(int index) {
                // called when an item is set
            }
        });
    }
}
  • 这部分的代码其实就是照套路来就成了,把官方文档中的实现代码贴过来,很容易看明白
  • count函数里面返回图片总数
  • populate函数里面:需要实现这一点以填充给定索引处的视图(我只是简单的拿过来用,其实这个我没有太理解,但是能模仿着用就成)

当你做到这里,你就可以运行你的程序了,一个完整的轮播图效果就实现了!!!

浅述启动页的实现

当你看完了上面轮播图的实现后,其实想要完成一个启动页的模拟效果,已经很接近啦,只要做一个动画效果,然后让其自动播放,然后在几秒后自动跳转到MainActivity页面就行了
我这里其实就是使用投机的方式,在网上找了一个自动点击页面的代码(设置动画为点击页面后开始),然后在启动页放一个线程,睡眠一段时间后跳转页面就行
详细请见源码https://github.com/lrhzds/MotionLayout_Demo

    <Transition
        motion:constraintSetEnd="@+id/end"
        motion:constraintSetStart="@id/start"
        motion:duration="5000"
        motion:motionInterpolator="cubic(0.09,0.15,0.34,0.86)">
        <KeyFrameSet.../>
        </KeyFrameSet>
        <OnClick motion:clickAction="transitionToEnd" />
    </Transition>

上面的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() {
            @Override
            public 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() {

            @Override
            public void run() {
                //1:休眠6S
                try {
                    Thread.sleep(6000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //进入主页面
                Intent it=new Intent(StartActivity.this,
                        MainActivity.class);
                startActivity(it);
            }
        });
        //2:启动这个子线程
        t.start();

插入gif图

请添加图片描述

如果对上面的gif图的插入有兴趣的话可以继续看后续的内容,如果没有那本篇博客的内容就到此结束啦,感谢您的观看!!!

//GIF
    implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.15'

只要导入上面的库,然后在activity里面直接使用就行

<pl.droidsonroids.gif.GifImageView
        android:id="@+id/gifImv1"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_weight="1"
        android:scaleType="fitXY"
        android:src="@drawable/d320c53c8d16cda0b7431627e897d2b2"
        app:layout_constraintBottom_toBottomOf="@id/g7"
        app:layout_constraintLeft_toLeftOf="@id/g3"
        app:layout_constraintRight_toRightOf="@id/g4"
        app:layout_constraintTop_toTopOf="@id/g7" />

官方文档

参考链接

作者:林睿航

原文链接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/55458.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

化妆品行业的数字进化论:S2B2B电商网站如何助力化妆品企业打造增长新动能

近年来&#xff0c;伴随着国家经济的快速发展和消费者对“美”的追求日益强烈&#xff0c;大大推动了化妆品行业的蓬勃发展&#xff0c;根据公开数据显示&#xff0c;2021年我国化妆品零售总额达4026亿元&#xff0c;较2020年同比增长18.40%&#xff0c;我国目前已成为全球第二…

一篇文章让你全方位掌握git版本控制管理

注&#xff1a;侵权请联系作者删除 目录 1.引入&#xff1a; 2.Git 的工作区域和流程 3.stash区域 4.git基本操作 A.git add B.git commit c.git pull D.git fetch E.git branch F.git init 5.在项目中实际运用案例&#xff1a; A.在github上创建一个新仓库 B.复制刚创建…

matlab使用hampel滤波,去除异常值

此示例显示了Hampel用于检测和删除异常值的过程的 实现。 最近我们被客户要求撰写关于hampel滤波的研究报告&#xff0c;包括一些图形和统计输出。 产生一个包含24个样本的随机信号x。 重置随机数生成器以获得可重复的结果。 rng defaultlx 24; x randn(1,lx); 围绕x的每…

网页前端知识汇总(六)——如何让网页全部内容显示成灰色

最近很多做网站前端的技术员是不是都接到了老板的任务&#xff0c;让网站的网页显示效果都变成灰色&#xff0c;这个也是随某些事件的发生或者某些专题内容觉得需要这样做的&#xff0c;大部分用于大家都不愿意看到的专题事件如某某烈士&#xff0c;逝去的伟人等&#xff1b;大…

Scala013--Scala中的方法

因为Scala是一种函数式编程语言&#xff0c;因此在Scala中基本上都是方法和函数&#xff0c;但是需要注意的是&#xff0c;在Java中方法和函数是同一个意思&#xff0c;但是在Scala中函数和方法的含义不同&#xff1a; 方法&#xff1a;是类和对象的成员函数&#xff1a;是对象…

jeecgboot-前端组件封装代码示例

首先我们要知道 jeecgboot他前台的组件代码封装文件夹的位置在src-components中&#xff0c;这时我们其实可以观察他们代码的写法(个人感觉学习代码的最好的途径就是临摹他人高质量的代码、多看、多写)路径如图&#xff1a; 接下来我们会在标注3下实现一个简单的自定义组件 代码…

【Eureka】【源码+图解】【八】Eureka客户端的服务获取

【Eureka】【源码图解】【七】Eureka的下线功能 目录7. 获取服务7.1 初始化HeartBeat的task7.2 将task进一步包装成定时timerTask7.3 定时时间到&#xff0c;执行timeTask7.4 task获得线程资源&#xff0c;执行refreshRegistry()7.5 服务端接受请求7.6 获取Applications7. 获取…

Spark - RDD 的分区和Shuffle

一、RDD 的分区 前面在学习 MapReduces 的时候就提到分区&#xff0c;在RDD中同样也存在分区的概念&#xff0c;本质上都是为了提高并行度&#xff0c;从而提高执行的效率&#xff0c;那在 Spark 中的分区该怎么设置呢&#xff1f; 首先分区不是越多越好&#xff0c;太多意味…

[Android]Logcat调试

Android采用Log(android.util.log)工具打印日志&#xff0c;它将各类日志划分为五个等级。 Log.e 打印错误信息 Log.w 打印警告信息 Log.i 打印一般信息 Log.d 打印调试信息 Log.v 打印冗余信息 不同等级的日志信息&#xff0c;在日志栏中会以不同颜色和等级(E、W、…

(附源码)ssm医院挂号系统 毕业设计 250858

医院挂号系统的设计与实现 摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对医院排队挂号等问…

深入理解 Python 描述符

学习 Python 这么久了&#xff0c;说起 Python 的优雅之处&#xff0c;能让我脱口而出的&#xff0c; Descriptor&#xff08;描述符&#xff09;特性可以排得上号。 描述符 是Python 语言独有的特性&#xff0c;它不仅在应用层使用&#xff0c;在语言语法糖的实现上也有使用到…

【java基础系列】16- Java中怎么处理异常?

Java的异常处理 1、异常的概念 概念&#xff1a;程序在运行过程中出现的不正常现象。出现异常不处理将终止程序运行。异常处理的必要性&#xff1a;任何程序都可以存在大量的未知问题、错误&#xff1b;如果不对这些问题进行正确处理&#xff0c;则可能导致程序的中断&#x…

[附源码]Python计算机毕业设计SSM开放性实验室网上预约管理(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

分布式和可再生系统建模(simulink)

目录 1 可再生/微电网概述 1.1 分布式和可再生系统建模和仿真 1.2 解决工作流程 1.3 能源管理系统监控设计 1.4 验证控件的测试网格规范和IEEE标准 1.5 部署算法和代码生成 1.6 网格集成研究控制器的实时测试 2 微电网案例 2.1 简介 2.2 在 Simulink 中实现微电网…

【JavaEE】初识操作系统,吃透进程

✨哈喽&#xff0c;进来的小伙伴们&#xff0c;你们好耶&#xff01; &#x1f6f0;️&#x1f6f0;️系列专栏:【JavaEE】 ✈️✈️本篇内容:初始操作系统&#xff0c;进程的概念 &#x1f680;&#x1f680;代码存放仓库gitee&#xff1a;JavaEE初阶代码存放&#xff01; ⛵⛵…

关于AM437x Linux+qt开发笔记(2)

第一部分,触摸屏 命令 lsinput (有些系统不移植)查看系统input实践 命令ox -d /dev/input/event1 或hexdump -d /dev/input/event1 (从上图看,event0没有接的触屏) ,点击屏幕如下 命令 ls /dev/input -al , 查看input设备的触摸屏软连接。 命令cat /etc/udev/ru…

编码与测试

文章目录一、编码1、概念2、如何选择程序设计语言3、程序设计风格&#xff08;1&#xff09;源程序文档化(2) 数据说明&#xff08;3&#xff09;语句构造&#xff08;4&#xff09;输入输出&#xff08;5&#xff09;程序效率编码时提高程序运行效率的主要规则二、软件测试基础…

【爬坑之路一】windows系统下更新升级node版本【亲测有效】

前言 一定要看到最后&#xff01;&#xff01;&#xff01; 项目开发中&#xff0c;需要升级 node 版本。本着不想卸载 node 再重新安装的原则&#xff0c;因为node 的环境配置以及各种相关配置有些繁琐&#xff0c;所以就想着使用 命令的方式进行升级。 在网上找了一些升级 n…

C#详解:程序域、程序集、模块、Type、反射

总结&#xff1a; ">>>":代表包含 进程>>>应用程序域AppDomain>>>程序集Assembly>>>模块Module>>>类型Type>>>成员&#xff08;方法、属性等&#xff09; 1、程序集Assembly 如图&#xff0c;假设一个解决方…

ARM 自己动手安装交叉编译工具链

一、Windows中装软件的特点 Windows中装软件使用安装包&#xff0c;安装包解压后有2种情况&#xff1a; 一种是一个安装文件&#xff08;.exe .msi&#xff09;&#xff0c;双击进行安装&#xff0c;下一步直到安装完毕。安装完毕后会在桌面上生成快捷方式&#xff0c;我们平…