MotionLayout,一篇文章带你了解Android最新的动画布局
/ 今日科技快讯 /
近日,国家市场监管总局网站发布对阿里、腾讯共11张行政处罚决定书。其中,市场监管总局发布对腾讯行政处罚决定书共九张,均为相关股权收购或设立合营企业构成未依法申报违法实施经营者集中。市场监管总局发布对阿里行政处罚书两张,同为设立合营企业或收购股权构成未依法申报违法实施经营者集中。
/ 作者简介 /
本篇文章来自android超级兵的投稿,文章深入分析了android MotionLayout的相关知识,相信会对大家有所帮助!同时也感谢作者贡献的精彩文章。
android超级兵的博客地址:
https://blog.csdn.net/weixin_44819566
/ 前言 /
环境
system : macOS
android studio : 4.1.3
constraintLayout : 2.0.4
gradle : gradle-6.7.1-bin
kotlin : 1.4.23
你需要知道什么
MotionLayout是ConstraintLayout的子类,具有ConstraintLayout所有功能。
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
使用as预览MotionLayout,as版本必须 >= 4.0。
/ 正文 /
使用 MotionLayout 创建动画
将原ConstraintLayout转换为MotionLayout布局。
转换之后:
可以看出,这里定义了一个Button,如果说在ConstraintLayout,这样写会有警告,让约束起来,但是这里并没有。
没有的原因是因为定义了MotionLayout的layoutDescription属性,需要在layoutDescription属性中写。
点击动画OnClick
onClick#clickAction说明
motion:clickAction=“toggle”
效果:
motion:clickAction=“transitionToEnd”
motion:clickAction=“jumpToEnd”
motion:clickAction=“jumpToStart”
不添加动画到开始。
motion:clickAction=“transitionToStart”
添加动画到开始。
多个view一起联动
例如这样:
效果图:
手指拖动OnSwipe
参数介绍:
motion:touchAnchorId 指的是您可以滑动并拖动的视图。
motion:touchAnchorSide 表示我们从右侧拖动视图。
motion:dragDirection 表示拖动的进度方向。
例如,motion:dragDirection=“dragRight”表示当您向右拖动时,进度会增加。
效果图:
辅助工具
motionLayout默认会自带调试工具。
官方说明图:
圆圈代表一个视图的开始或结束位置。
线条代表一个视图的路径。
菱形代表KeyPosition修改路径。
还有一种使用视图的方式来调试:
修改路径(KeyPosition)
修改路径可以通过右侧可视化工具来进行:
详解图
再来看看自动生成的代码:
KeyPosition参数详解:
motion:motionTarget="@+id/button" 需要移动轨迹的view
motion:framePosition="[0-100]" framePosition是一个介于 0 和 100 之间的数字。它定义了在动画KeyPosition中的应用时间,1 表示 1% 的动画,99 表示 99% 的动画
motion:keyPositionType=“keyPositionType”这是如何KeyPosition修改路径。它可以是parentRelative,pathRelative,或deltaRelative
percentX | percentY是修改路径的量framePosition(值介于 0.0 和 1.0 之间,允许负值和值 >1)
这里motion:keyPositionType参数解释一下:
parentRelative
这里设置了4个点,分别为:
假设现在移动起始点1,deltaRelative会以开始点和起始点2来构建一个“贝塞尔环境”来生成对应的路径,这里和pathRelative效果类似但也有不同之处!
pathRelative和deltaRelative的区别:
pathRelative不需要依靠起始点和结束点就可以拖动
deltaRelative 起始点和结束点在同一x轴上会导致动画路径不按照贝塞尔路径执行
而是执行一条直线
最终效果长这样:
效果都一样,就只放一个喽,需要的请下载源码观看。
KeyPosition配合pathMotionArc进阶
pathMotionArc见名之意就知道是用来画弧形的。先来看pathMotionArc简单的例子:
可以看出,想要画一条优雅的弧线很简单,只需要在开始点设置motion:pathMotionArc="startHorizontal"即可。
⚠️ motion:pathMotionArc是需要2个点才生效的,默认是开始点和结束点
如何设置多个点呢?例如这样,也可以设置两个弧形的比例大小等。
位置坐标说明:
pathMotionArc类型介绍:
startVertical 向下的弧形
startHorizontal 向上的弧形
none 直线
flip 和上一个点如果上一个点是startVertical,,那么当前就是startHorizontal,可以理解为反转
类型说明效果图
开始点:motion:pathMotionArc="startVertical"
起始点1:motion:pathMotionArc="startVertical"
起始点2:motion:pathMotionArc=“flip”
效果代码:
<?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"><Transitionmotion:constraintSetEnd="@+id/end"motion:constraintSetStart="@id/start"motion:duration="1000"><!-- 点击事件 --><OnClickmotion:clickAction="toggle"motion:targetId="@id/button6" /><KeyFrameSet><!-- 起始点1 和 起始点2设置"关联" --><KeyPositionmotion:framePosition="40"motion:keyPositionType="deltaRelative"motion:motionTarget="@+id/button6"motion:pathMotionArc="startVertical"motion:percentX="0.358"motion:percentY="0.17" /><!-- 起始点2 和结束关联 --><KeyPositionmotion:framePosition="79"motion:keyPositionType="deltaRelative"motion:motionTarget="@+id/button6"motion:pathMotionArc="flip"motion:percentX="0.675"motion:percentY="0.568" /></KeyFrameSet></Transition><!-- start --><ConstraintSet android:id="@+id/start"><!-- 开始点 和起始点1设置"关联" --><Constraintandroid:id="@+id/button6"android:layout_width="80dp"android:layout_height="80dp"motion:layout_constraintBottom_toBottomOf="parent"motion:layout_constraintLeft_toLeftOf="parent"motion:layout_constraintTop_toTopOf="parent"motion:pathMotionArc="startVertical" /></ConstraintSet><!-- end --><!-- 结束点不设置关联。。 --><ConstraintSet android:id="@+id/end"><Constraintandroid:id="@+id/button6"android:layout_width="64dp"android:layout_height="64dp"motion:layout_constraintBottom_toBottomOf="parent"motion:layout_constraintRight_toRightOf="parent" /></ConstraintSet>
</MotionScene>
这里比例也是能改变的,例如这样:
这里还是比较简单的,自己动手试试就懂啦!
改变属性状态(KeyAttribute)
看一眼代码:
<?xml version="1.0" encoding="utf-8"?>
<MotionScene x<?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"><Transitionmotion:constraintSetEnd="@+id/结束了"motion:constraintSetStart="@id/开始了"motion:duration="1000"><KeyFrameSet><!-- 改变属性状态 --><KeyAttributemotion:motionTarget="@+id/button7"motion:framePosition="22"android:alpha="0.2" /></KeyFrameSet><OnClickmotion:clickAction="toggle"motion:targetId="@id/button7" /></Transition><!-- 开始 这里也可以定义中文,但是不建议使用。。 --><ConstraintSet android:id="@+id/开始了"><Constraintandroid:id="@+id/button7"android:layout_width="60dp"android:layout_height="60dp"motion:layout_constraintBottom_toBottomOf="parent"motion:layout_constraintLeft_toLeftOf="parent"motion:layout_constraintTop_toTopOf="parent" /></ConstraintSet><!-- 结束 这里也可以定义中文,但是不建议使用。。--><ConstraintSet android:id="@+id/结束了"><Constraintandroid:id="@+id/button7"android:layout_width="60dp"android:layout_height="60dp"motion:layout_constraintBottom_toBottomOf="parent"motion:layout_constraintRight_toRightOf="parent"motion:layout_constraintTop_toTopOf="parent" /></ConstraintSet>
</MotionScene>
mlns:android="http://schemas.android.com/apk/res/android"xmlns:motion="http://schemas.android.com/apk/res-auto"><Transitionmotion:constraintSetEnd="@+id/end"motion:constraintSetStart="@id/start"motion:duration="1000"><!-- 点击事件 --><OnClickmotion:clickAction="toggle"motion:targetId="@id/button6" /><KeyFrameSet><!-- 起始点1 和 起始点2设置"关联" --><KeyPositionmotion:framePosition="40"motion:keyPositionType="deltaRelative"motion:motionTarget="@+id/button6"motion:pathMotionArc="startVertical"motion:percentX="0.358"motion:percentY="0.17" /><!-- 起始点2 和结束关联 --><KeyPositionmotion:framePosition="79"motion:keyPositionType="deltaRelative"motion:motionTarget="@+id/button6"motion:pathMotionArc="flip"motion:percentX="0.675"motion:percentY="0.568" /></KeyFrameSet></Transition><!-- start --><ConstraintSet android:id="@+id/start"><!-- 开始点 和起始点1设置"关联" --><Constraintandroid:id="@+id/button6"android:layout_width="80dp"android:layout_height="80dp"motion:layout_constraintBottom_toBottomOf="parent"motion:layout_constraintLeft_toLeftOf="parent"motion:layout_constraintTop_toTopOf="parent"motion:pathMotionArc="startVertical" /></ConstraintSet><!-- end --><!-- 结束点不设置关联。。 --><ConstraintSet android:id="@+id/end"><Constraintandroid:id="@+id/button6"android:layout_width="64dp"android:layout_height="64dp"motion:layout_constraintBottom_toBottomOf="parent"motion:layout_constraintRight_toRightOf="parent" /></ConstraintSet>
</MotionScene>
改变alpha值:
当然也可以设置多个属性,例如这样:
自行探索
android:visibility
android:alpha
android:elevation
android:rotation
android:rotationX
android:rotationY
android:scaleX
android:scaleY
android:translationX
android:translationY
android:translationZ
KeyAttribute配合CustomAttribute设置颜色
CustomAttribute常用来设置view颜色的,是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"><Transitionmotion:constraintSetEnd="@+id/end"motion:constraintSetStart="@id/start"motion:duration="1000"><!--点击--><OnClickmotion:clickAction="toggle"motion:targetId="@id/imageView8" /><KeyFrameSet><!-- 旋转3圈到 100点 --><KeyAttributeandroid:rotation="-720"motion:framePosition="100"motion:motionTarget="@id/imageView8" /><!-- 0点 的时候黑色 --><KeyAttributemotion:framePosition="0"motion:motionTarget="@id/imageView8"><CustomAttributemotion:attributeName="colorFilter"motion:customColorValue="#000000" /></KeyAttribute><!-- 50点的时候红色 --><KeyAttributemotion:framePosition="50"motion:motionTarget="@id/imageView8"><CustomAttributemotion:attributeName="colorFilter"motion:customColorValue="#E91E63" /></KeyAttribute><!-- 100点的时候黑色 --><KeyAttributemotion:framePosition="100"motion:motionTarget="@id/imageView8"><CustomAttributemotion:attributeName="colorFilter"motion:customColorValue="#000000" /></KeyAttribute></KeyFrameSet></Transition><ConstraintSet android:id="@+id/start" ... /><ConstraintSet android:id="@+id/end" ... />
</MotionScene>
在里面CustomAttribute你必须指定一个attributeName和一个值来设置。
motion:attributeName是此自定义属性将调用的setter的名称。在这个例子中, setColorFilteronDrawable将被调用。
motion:customColorValue是名称中注明的类型的自定义值,在此示例中,自定义值是指定的颜色。
自定义值可以具有以下任何类型:
Color
Integer
Float
String
Dimension
Boolean
来看效果图就懂了。
设置抖动[KeyCycle]
如何创建
关键代码
<Transitionmotion:constraintSetEnd="@+id/end"motion:constraintSetStart="@id/start"motion:duration="1000"><!--点击--><OnClick ... /><KeyFrameSet><!--motion:waveOffset 添加到属性的偏移值motion:wavePeriod 要在此区域附近循环的循环数motion:waveShape="cos"sin|square|triangle|sawtooth|reverseSawtooth|cos|bounce正弦| 方形 |三角形 | 锯齿 | 反向锯齿 |cos| 反弹--><KeyCycleandroid:alpha="0.5"android:scaleY="1.2"android:scaleX="1.2"motion:framePosition="51"motion:motionTarget="@+id/imageView8"motion:waveOffset="2"motion:wavePeriod="1"motion:waveShape="sin" /></KeyFrameSet></Transition>
参数介绍:
motion:waveOffset 添加到属性的偏移值
motion:wavePeriod 要在此区域附近循环的循环数
motion:waveShape=“cos”
sin|square|triangle|sawtooth|reverseSawtooth|cos|bounce
各大类型效果图:
(具体效果可以去原文进行查看)
设置抖动(KeyTimeCycle)
KeyTimeCycle和KeyCycle使用起来是一样的,参数也是一样的。
有一点不同的是,一般KeyTimeCycle是三个一起使用,通过3个KeyTimeCycle定义一个准确的循环关键帧。
可以看出,只有在第50帧的时候,会发生改变,因为第50帧的时候设置motion:wavePeriod为1。
motion:wavePeriod:要在此区域附近循环的循环数
改变控件属性(KeyTrigger)
什么叫改控件属性?如何控制?
首先自定义ImageView,里面就2个方法,show和hide。
class KeyTriggerImageView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) :AppCompatImageView(context, attrs, defStyleAttr) {// 显示 viewfun show() {visibility = View.VISIBLE}// 隐藏当前 viewfun hide() {visibility = View.GONE}
}
如何使用:
<?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"><Transitionmotion:constraintSetEnd="@+id/end"motion:constraintSetStart="@id/start"motion:duration="2000"><!--点击--><OnClickmotion:clickAction="toggle"motion:targetId="@id/imageView11" /><KeyFrameSet><KeyTriggermotion:framePosition="0"motion:motionTarget="@+id/imageView11"motion:onCross="show" /><KeyTriggermotion:framePosition="20"motion:motionTarget="@+id/imageView11"motion:onCross="hide" /><KeyTriggermotion:framePosition="60"motion:motionTarget="@+id/imageView11"motion:onCross="show" /><KeyTriggermotion:framePosition="79"motion:motionTarget="@+id/imageView11"motion:onCross="hide" /><KeyTriggermotion:framePosition="100"motion:motionTarget="@+id/imageView11"motion:onCross="show" /></KeyFrameSet></Transition><ConstraintSet android:id="@+id/start" .../><ConstraintSet android:id="@+id/end" .../>
</MotionScene>
KeyTrigger参数介绍:
motion:onCross 调用的方法名字
motion:framePosition 当前是第几帧 (0-100)
motion:motionTarget 设置的控件id
来看一眼效果:
根据这个思路,是不是就可以在滑动的过程中替换图标显示,例如这样:
再来一张辅助图,现在应该是非常清晰了!!
加速与减速(Easing)
也是一个参数的效果,使用很简单,直接看代码:
<?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"><Transitionmotion:constraintSetEnd="@+id/end"motion:constraintSetStart="@id/start"motion:duration="1000"><!--点击--><OnClickmotion:clickAction="toggle"motion:targetId="@id/imageView13" /><KeyFrameSet></KeyFrameSet></Transition><!-- 开始 --><ConstraintSet android:id="@+id/start"><!-- motion:transitionEasing 设置加速度 or 减速 类型 --><Constraintandroid:id="@+id/imageView13"android:layout_width="100dp"android:layout_height="100dp"motion:layout_constraintBottom_toBottomOf="parent"motion:layout_constraintLeft_toLeftOf="parent"motion:transitionEasing="acclerate" /></ConstraintSet><!-- 结束--><ConstraintSet android:id="@+id/end"><Constraintandroid:id="@+id/imageView13"android:layout_width="100dp"android:layout_height="100dp"motion:layout_constraintRight_toRightOf="parent"motion:layout_constraintTop_toTopOf="parent" /></ConstraintSet>
</MotionScene>
实战
先来看看实战效果:
布局长这样:
需求分析:
类似皮皮虾点击评论功能
点击评论按钮时候,图片缩小,底下弹出一个recyclerview来显示评论
recyclerview显示的时候,评论按钮不显示
recyclerview不显示的时候,评论按钮显示
activity_motion_layout_9_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"><Transitionmotion:constraintSetEnd="@+id/end"motion:constraintSetStart="@id/start"motion:duration="400"><OnClickmotion:clickAction="toggle"motion:targetId="@id/imageComment" /><OnSwipemotion:dragDirection="dragUp"motion:touchAnchorId="@id/recyclerView" /></Transition><!-- 开始 --><ConstraintSet android:id="@+id/start"><Constraintandroid:id="@+id/image"android:layout_width="match_parent"android:layout_height="match_parent"motion:layout_constraintBottom_toBottomOf="parent"motion:layout_constraintLeft_toLeftOf="parent"motion:layout_constraintRight_toRightOf="parent"motion:layout_constraintTop_toTopOf="parent" /><Constraintandroid:id="@+id/imageComment"android:layout_width="40dp"android:layout_height="40dp"android:layout_marginRight="@dimen/dp_10"android:alpha="1"motion:layout_constraintBottom_toBottomOf="parent"motion:layout_constraintRight_toRightOf="parent"motion:layout_constraintTop_toTopOf="parent"motion:layout_constraintVertical_bias="0.7" /><Constraintandroid:id="@+id/recyclerView"android:layout_width="match_parent"android:layout_height="0dp"motion:layout_constraintTop_toBottomOf="@id/image" /></ConstraintSet><!-- 结束 --><ConstraintSet android:id="@+id/end"><Constraintandroid:id="@+id/image"android:layout_width="match_parent"android:layout_height="0dp"motion:layout_constraintBottom_toTopOf="@id/recyclerView"motion:layout_constraintLeft_toLeftOf="parent"motion:layout_constraintRight_toRightOf="parent"motion:layout_constraintTop_toTopOf="parent" /><Constraintandroid:id="@+id/recyclerView"android:layout_width="match_parent"android:layout_height="500dp"motion:layout_constraintBottom_toBottomOf="parent"motion:layout_constraintTop_toBottomOf="@id/image" /><Constraintandroid:id="@+id/imageComment"android:layout_width="40dp"android:layout_height="40dp"android:layout_marginRight="@dimen/dp_10"android:alpha="0"motion:layout_constraintBottom_toBottomOf="parent"motion:layout_constraintRight_toRightOf="parent"motion:layout_constraintTop_toTopOf="parent"motion:layout_constraintVertical_bias="0.7" /></ConstraintSet>
</MotionScene>
走到这里基本上就完事了。
/ 总结 /
大致结构:
<Transitionapp:constraintSetStart="@+id/start"app:constraintSetEnd="@+id/end"app:duration="1000"><!-- 拖动 --><OnSwipe /><!-- 点击 --><OnClick /><KeyFrameSet ><KeyAttribute><CustomAttribute/></KeyAttribute><KeyPostion/><KeyCycle/><KeyTimeCycle/></KeyFrameSet><!--用于过渡动画的起始点状态参数配置--><Constraint android:id="@id/viewId"><!-- 运动模型: 弧线路路径,时间模型等 --><Motion/><!--布局相关注意: width 、 height 和 margin 的命名空间是 android: (beta1 开始)而约束相关的命名空间是 app (或 motion )--><Layout/><!-- 动画变换:做旋转,位移,缩放,海海拔等属性 --><Transform/><!--自定义属性attributeName 会加上 set/get 反射找到真正的函数名,⽐如 backgroundColor 就会调用 setBackgroundColor() 函数custom(xxx)Value 对应属性的数据类型--><CustomAttribute/><!--特定的属性visibility 、alpha 等属性--><PropertySet/></Constraint><!--用于过渡动画的结束点状态参数配置--><ConstraintSet android:id="@+id/end"../>
</Transition>
完整代码地址:
https://gitee.com/lanyangyangzzz/android_ui/tree/master
推荐阅读:
我的新书,《第一行代码 第3版》已出版!
从SplashScreen深度探讨App启动画面的前世今生
再看LayoutInflater,这次你可能又会有新的认识
欢迎关注我的公众号
学习技术或投稿
长按上图,识别图中二维码即可关注
MotionLayout,一篇文章带你了解Android最新的动画布局相关推荐
- 一篇文章带你走近Android自定义view
系列文章目录 一篇文章带你走近Android自定义view 文章目录 系列文章目录 前言 一.为什么要自定义view 二.先看看一个超级简单的自定义view(三个构造函数) 三.了解手机的坐标系 四. ...
- android中uvc调用usb摄像头,一篇文章带你了解Android Usb摄像头
在实际项目中,有些客户可能需要支持usb摄像头功能,如果你也遇到usb摄像头支持的问题,那这篇文章一定能帮助到你. 目前android是支持uvc协议的,也就是只要我们采用的usb摄像头是支持uvc协 ...
- 一篇文章带你入门adb自动化测试
一篇文章带你入门adb自动化测试 前言 一.什么是adb 1.adb的原理的应用场景 2.(adb)Android debug bridge用于调试使用安卓系统的设备 3.adb基本原理 二.adb环 ...
- 一篇文章带你了解Flannel
from: http://dockone.io/article/618 DockOne技术分享(十八):一篇文章带你了解Flannel [编者的话]Flannel是 CoreOS 团队针对 Kuber ...
- 一篇文章带你领悟 Frida 的精髓(基于安卓8.1)
转载(一篇文章带你领悟Frida的精髓(基于安卓8.1)):https://www.freebuf.com/articles/system/190565.html <Frida操作手册>: ...
- java ee 值范围_一篇文章带你读懂: Java EE
原标题:一篇文章带你读懂: Java EE 点击上图,查看教学大纲 何为 Java EE Java EE是一个标准中间件体系结构 不要被名称"Java PlatformEnterprise ...
- 学习笔记-一篇文章带你领悟frida的精髓
一篇文章带你领悟frida的精髓(基于安卓8.1) frida是啥? frida为什么这么火? frida实操环境 基本能力Ⅰ:hook参数.修改结果 基本能力Ⅱ:参数构造.方法重载.隐藏函数的处理 ...
- 借重新装系统之际,一篇文章带你玩透Windows 10从系统安装到软件选择
系统安装所需软件 Rufus 一个制作USB-ISO的免费软件,比微软官方工具好的地方在于除了可以制作windows 系统U盘,还可以制作linux 以及安卓X86的系统安装光盘. 借重新装系统之际, ...
- 一篇文章带你详解 TCP/IP 协议(下)
前面的第一二三章已在上篇讲解,还没看过的可以先看看:一篇文章带你详解 TCP/IP 协议(上) 本文继续讲解第四章. 四.网络层中的 IP 协议 IP(IPv4.IPv6)相当于 OSI 参考模型中的 ...
最新文章
- C++ 笔记(10)— 运算符(算术、关系、逻辑、位运算、赋值和其它运算符)
- 3的三个整数立方和有多少个解?全球40万台计算机助力,MIT研究登上PNAS
- Mastercam X4中文版三维造型设计基础与典型范例
- Oracle11gR2 64bit+Oracle11gR2Client32bit+pl/sql 9
- 国内技术原创氛围为什么那么差?记EAWorld(普元)是如何靠“借鉴”产出原创文章的!
- Demon_接金币(三个掉落物品预设体,一接物体的工具)
- C# TextBox改变高度的方法(转载)
- golang中如何使用http,socket5代理
- TypeScript算法专题 - blog2 - 单链表节点的索引、结点删除与链表反转
- 2015 年总结 - 十年
- 支付宝弄了个“双12 ” 岛国民众都high了
- Head First设计模式整理
- Latex公式空格输入
- Python入门基础(8)--私有化属性和方法/Property属性/_new_方法/单例模式/错误和异常处理/Python动态添加属性和方法/_slots_属性
- 灵感爆发:An/flash 影片剪辑动画播放一遍后,摆脱paly()的控制
- 迅雷离线下载脚本 — LinuxTOY
- 多文件批量下载打包成.zip
- 用matlab对图像进行边缘填充,matlab中的图像边界填充函数 | 学步园
- 现代微型计算机的字长,计算机的字长
- java——final关键字、权限、内部类、引用类型
热门文章
- IE浏览器打开闪退,自动切换MicrosoftEdge浏览器
- php验证码无法验证问题,php无法显示验证码
- PMP第四章:项目整合管理
- 用anaconda启动Spyder报错
- 图像处理(六)——图像压缩
- 什么是4:4:4、4:2:2、4:2:0?了解图像压缩取样的方式
- 除了X站,程序员还喜欢上这些网站...
- 2007-11-20 多普达828+不完全技术分析 [zozo转及对话]
- 头条校招(今日头条2017秋招真题)1——python解法
- 2022-2027年中国巴西鲷鱼养殖行业市场调研及未来发展趋势预测报告