Android动画之圆形揭露动画

什么是圆形揭露动画 圆形揭露动画,可以让一个View裁剪成一个圆形,并以指定的圆心做半径变化动画。当您显示或隐藏一组界面元素时,可给用户提供视觉连续性。 使用圆形揭露动画 通过调用ViewAnimationUtils.createCircularReveal()返回一个Animator实例,调用animator.start()显示动画。 createCircularReveal() 动画采用五个参数。 属性 描述 View 即要执行动画的View centerX 指定圆心的x点坐标 centerY 指定圆心的y点坐标 startRadius 动画开始前剪裁圆形的半径 endRadius 动画结束时的圆形半径 findViewById<Button>(R.id.btn_circle_scale_down).setOnClickListener { val image = findViewById<ImageView>(R.id.img_circle) val width = image.width val height = image.height image.visibility = View.VISIBLE ViewAnimationUtils.createCircularReveal( image, width / 2, height / 2, 0F, width.toFloat() ).apply { duration = 2000L }.also { it.start() } }

April 24, 2022

Android开发——颜色

Android中的颜色值通常遵循RGB/ARGB标准,使用时通常以“ # ”字符开头的8位16进制表示。其中ARGB 依次代表透明度(Alpha)、红色(Red)、绿色(Green)、蓝色(Blue),取值范围为0 ~ 255(即16进制的0x00 ~ 0xff)。 透明度参考表 透明度 取值 100% 00 95% 0D 90% 1A 85% 26 80% 33 75% 40 70% 4D 65% 59 60% 66 55% 73 50% 80 45% 8C 40% 99 35% A6 30% B3 25% BF 20% CC 15% D9 10% E6 5% F2 0% FF

April 20, 2022

Android MVP架构

什么是MVP? MVP的全称为Model-View-Presenter,Model提供数据,View负责显示,Controller/Presenter负责逻辑的处理。 来自维基百科的模型描述 Model-View-Presenter (MVP) 是用户界面设计模式的一种,被广泛用于便捷自动化单元测试和在呈现逻辑中改良分离关注点(separation of concerns)。 Model 定义用户界面所需要被显示的资料模型,一个模型包含着相关的业务逻辑。 View 视图为呈现用户界面的终端,用以表现来自 Model 的资料,和用户命令路由再经过 Presenter 对事件处理后的资料。 Presenter 包含着组件的事件处理,负责检索 Model 获取资料,和将获取的资料经过格式转换与 View 进行沟通。 Android 实现 代码参考谷歌官方的Demo。To-DoApp的todo-mvp-kotlin分支 1. 定义BaseView和BasePresenter 其中BaseView持有一个presenter成员。实现BasePresenter要实现start()方法。 interface BaseView<T> { var presenter: T } interface BasePresenter { fun start() } 2.明确功能需求,编写功能级的View和Presenter 以Task详情页为例,用户能执行4种操作,分别是编辑Task、删除Task、改变Task完成状态(已完成、未完成)。根据上面的需求,我们Task详情页的Presenter代码如下。 interface Presenter : BasePresenter { // 编辑Task fun editTask() // 删除Task fun deleteTask() // 完成Task fun completeTask() // 激活Task fun activateTask() } interface View : BaseView<Presenter> { val isActive: Boolean // 是否显示加载中 fun setLoadingIndicator(active: Boolean) // 显示找不到Task fun showMissingTask() // Task为空时,隐藏标题 fun hideTitle() // 显示并显示标题 fun showTitle(title: String) // Task为空时,隐藏描述 fun hideDescription() // 显示并显示描述 fun showDescription(description: String) // 显示Task的完成状态 fun showCompletionStatus(complete: Boolean) // 跳转编辑Task的Activity fun showEditTask(taskId: String) // 执行Task删除后的逻辑 fun showTaskDeleted() // 显示Task已完成的界面 fun showTaskMarkedComplete() // 显示Task已已激活的界面 fun showTaskMarkedActive() } 3.业务代码分析 TaskDetailActivity是容器,具体实现逻辑在TaskDetailFragment。 在TaskDetailActivity里,将TaskDetailPresenter和TaskDetailFragment(已实现View接口) 绑定在一起,如何绑定见下文2。 ...

April 19, 2022

Android动画之视图动画

Android View 动画框架 Animation框架定义了透明度、旋转、缩放和位移几种常见的动面,而且控制的是整个view,实现原理是每次绘制视图时 View 所在的 ViewGroup 中的drawChild 函数获取该 View 的Animation 的 Transformation 值,然后调用 canvas.concat(transformToApply.getMatrix()),通过矩阵运算完成动画帧。如果动画没有完成,就继续调用 invalidate()函数,启动下次绘制來驱动动画,从而完成整个动画的绘制。——《Android群英传》 视图动画四种动画方式 AlphaAnimation(透明度动画) 为视图添加透明度的变换动画。 构建AlphaAnimation2个参数 属性 属性描述 fromAlpha 开始的透明度 toAlpha 结束的透明度 //透明度从0到1,时长1秒 private fun alphaAnimation(v: View) { with(AlphaAnimation(0F, 1F)) { duration = 1000 v.startAnimation(this) } } RotateAnimation(旋转动画) 为视图增加旋转的变换动画。 构建RotateAnimation6个参数 属性 属性描述 fromDegrees 旋转开始的角度 toDegrees 旋转结束的角度 pivotXType 旋转中心点X的类型:ABSOLUTE (默认)表示X值是View的绝对坐标;RELATIVE_TO_SELF表示X值是View宽度的百分比;RELATIVE_TO_PARENT表示X值是父布局宽度的百分比。 pivotXValue 旋转中心点X的取值(默认为0)。如果 pivotXType 不是 ABSOLUTE,则取值范围是0.0到1.0。 pivotYType 旋转中心点Y的类型:ABSOLUTE (默认)表示Y值是View的绝对坐标;RELATIVE_TO_SELF表示Y值是View高度的百分比;RELATIVE_TO_PARENT表示Y值是父布局高度的百分比。 pivotYValue 旋转中心点Y的取值(默认为0)。如果 pivotYType 不是 ABSOLUTE,则取值范围是0.0到1.0。 //以View的(0,0)点为中心(即左上角),从0度旋转到360度,时长1秒。 private fun rotateAnimation(v: View) { with(RotateAnimation(0F, 360F, 0F, 0F)) { duration = 1000 v.startAnimation(this) } } //以View的宽高一半的点为中心(即View正中心),从0度旋转到360度,时长1秒。 private fun rotateSelfAnimation(v: View) { with( RotateAnimation( 0F, 360F, RotateAnimation.RELATIVE_TO_SELF, 0.5F, RotateAnimation.RELATIVE_TO_SELF, 0.5F ) ) { duration = 1000 v.startAnimation(this) } } TranslateAnimation(位移动画) 为视图移动时增加位移动画。 构建TranslateAnimation的8个参数 属性 属性描述 fromXType 移动前X的取值类型:ABSOLUTE (默认)表示View的绝对值;RELATIVE_TO_SELF表示View宽度的百分比;RELATIVE_TO_PARENT表示父布局宽度的百分比。 fromXValue 移动前的X位置(如果fromXType不是ABSOLUTE,则取值范围是0.0到1.0)。 toXType 移动后X的取值类型:ABSOLUTE (默认)表示View的绝对值;RELATIVE_TO_SELF表示View宽度的百分比;RELATIVE_TO_PARENT表示父布局宽度的百分比。 toXValue 移动后的X位置(如果toXType不是ABSOLUTE,则取值范围是0.0到1.0)。 fromYType 移动前Y的取值类型:ABSOLUTE (默认)表示View的绝对值;RELATIVE_TO_SELF表示View高度的百分比;RELATIVE_TO_PARENT表示父布局高度的百分比。 fromYValue 移动前的Y位置(如果fromYType不是ABSOLUTE,则取值范围是0.0到1.0)。 toYType 移动后Y的取值类型:ABSOLUTE (默认)表示View的绝对值;RELATIVE_TO_SELF表示View高度的百分比;RELATIVE_TO_PARENT表示父布局高度的百分比。 toYValue 移动后的Y位置(如果toYType不是ABSOLUTE,则取值范围是0.0到1.0)。 //以View(0,0)点即左上角移到(200,300)的位置,时长1秒 private fun translateAnimation(v: View) { with(TranslateAnimation(0F, 200F, 0F, 300F)) { duration = 1000 v.startAnimation(this) } } ScaleAnimation(缩放动画) 为视图的缩放增加动画效果。 构建ScaleAnimation的8个参数 属性 属性描述 fromX 水平方向初始缩放比例。 toX 水平方向结束缩放比例。 fromY 垂直方向初始缩放比例。 toY 垂直方向结束缩放比例。 pivotXType 缩放中心点X的取值类型:ABSOLUTE (默认)表示View的绝对值;RELATIVE_TO_SELF表示View宽度的百分比;RELATIVE_TO_PARENT表示父布局宽度的百分比。 pivotXValue 动画缩放中心点的X值(默认为0)。如果 pivotXType 不是ABSOLUTE,则取值范围是0.0到1.0。 pivotYType 缩放中心点Y的取值类型:ABSOLUTE (默认)表示View的绝对值;RELATIVE_TO_SELF表示View高度的百分比;RELATIVE_TO_PARENT表示父布局高度的百分比。 pivotYValue 动画缩放中心点的Y值(默认为0)。如果 pivotYValue 不是ABSOLUTE,则取值范围是0.0到1.0。 //以View(0,0)点即左上角从宽高为0缩放到原宽高的2倍,时长1秒 private fun scaleAnimation(v: View) { with(ScaleAnimation(0F, 2F, 0F, 2F)) { duration = 1000 v.startAnimation(this) } } //以View的宽高一半的点为中心(即View正中心)从宽高为0缩放到原宽高的1倍,时长1秒 private fun scaleSelfAnimation(v: View) { with( ScaleAnimation( 0F, 1F, 0F, 1F, Animation.RELATIVE_TO_SELF, 0.5F, Animation.RELATIVE_TO_SELF, 0.5F ) ) { duration = 1000 v.startAnimation(this) } } AnimationSet(动画集合) 通过AnimationSet可以将动画以组合的形式展现出来 构造AnimationSet的1个参数 shareInterpolator 是否集合内的动画和AnimationSet公用一个插值器,否则每个动画各用回自己的插值器。 private fun animationSet(v: View) { val animationSet = AnimationSet(true).apply { duration = 1000 } val alpha = AlphaAnimation(0F, 1F).apply { duration = 1000 } animationSet.addAnimation(alpha) val translate = TranslateAnimation(0F, 100F, 0F, 200F).apply { duration = 1000 } animationSet.addAnimation(translate) v.startAnimation(animationSet) }

April 19, 2022

Android序列化之Parcelable

1、什么是Parcel Container for a message (data and object references) that can be sent through an IBinder. A Parcel can contain both flattened data that will be unflattened on the other side of the IPC (using the various methods here for writing specific types, or the general Parcelable interface), and references to live IBinder objects that will result in the other side receiving a proxy IBinder connected with the original IBinder in the Parcel. ...

March 16, 2022

Android动画之帧动画

帧动画是什么 首先动画本质就是连成连贯动作的一帧帧静态图快速切换的效果。帧:就是影像动画中最小单位的单幅影像画面,相当于电影胶片上的每一格镜头。一帧就是一副静止的画面,连续的帧就形成动画,如电视图象等。 在Android实现帧动画 1、准备素材 将图片资源放在drawable文件夹。如图所示👇 2、编写动画资源文件 在drawable文件夹下新建frame_anim.xml文件。文件内容如下 <?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/animation1" android:duration="200" /> <item android:drawable="@drawable/animation2" android:duration="200" /> <item android:drawable="@drawable/animation3" android:duration="200" /> <item android:drawable="@drawable/animation4" android:duration="200" /> <item android:drawable="@drawable/animation5" android:duration="200" /> <item android:drawable="@drawable/animation6" android:duration="200" /> <item android:drawable="@drawable/animation7" android:duration="200" /> <item android:drawable="@drawable/animation8" android:duration="200" /> <item android:drawable="@drawable/animation9" android:duration="200" /> <item android:drawable="@drawable/animation10" android:duration="200" /> <item android:drawable="@drawable/animation11" android:duration="200" /> <item android:drawable="@drawable/animation12" android:duration="200" /> </animation-list> 3、添加显示帧动画的ImageView <ImageView android:id="@+id/img_frame" android:layout_width="wrap_content" android:layout_height="wrap_content" tools:src="@mipmap/ic_launcher" /> 4、编写实现帧动画的代码 findViewById<ImageView>(R.id.img_frame).apply { setBackgroundResource(R.drawable.frame_anim) frameAnimation = background as AnimationDrawable tvOneShot.text = "OneShot:${frameAnimation.isOneShot}" } //开始动画 findViewById<Button>(R.id.btn_start).setOnClickListener { frameAnimation.start() } 5、效果 no_one_shot one_shot

March 15, 2022