用flash做的网站,重庆制作网站公司简介,wordpress apicloud,网站建设接外包流程图目录
#x1f4c2; 前言
AR 眼镜系统版本
拍照/录像动效切换
1. #x1f531; 技术方案
1.1 技术方案概述
1.2 实现方案
1#xff09;第一阶段动效
2#xff09;第二阶段动效
2. #x1f4a0; 默认代码配置
2.1 XML 初始布局
2.2 监听滑动对 View 改变
3. ⚛️…
目录 前言
AR 眼镜系统版本
拍照/录像动效切换
1. 技术方案
1.1 技术方案概述
1.2 实现方案
1第一阶段动效
2第二阶段动效
2. 默认代码配置
2.1 XML 初始布局
2.2 监听滑动对 View 改变
3. ⚛️ 拍照/录像动效切换实现
3.1 第一阶段动效
1左移右边部分的 View
2放大右边部分的 View
3.2 第二阶段动效
1动态调整右边部分的约束
2缩小右边部分的 View
3从左往右移动左边部分
4从 0 到 1 透明度增加左边部分
5动画集实现
6还原默认约束
4. ✅ 小结
附录1动效帮助类代码 前言
AR 眼镜系统版本 W517 Android9。
拍照/录像动效切换 实现效果如上 GIF 的左下角所示我们看到主要分为两部分、两阶段。 两部分左边部分为 Normal 状态 View右边部分为带有文字描述的 View。 两阶段右边部分分为变大阶段、缩小阶段在右边部分的第二缩小阶段时会触发左边部分的从左往右移动阶段、从 0 到 1 透明度增加阶段。 1. 技术方案
1.1 技术方案概述 拍照/录像动效切换主要使用属性动画完成同时对于放大和缩小的参考方向不同所以需要动态调整约束动态调整约束时还需注意 maigin 值因为文字改变尺寸也会变化。
1.2 实现方案
1第一阶段动效 左移右边部分的 View 放大右边部分的 View。
2第二阶段动效 动态调整右边部分的约束 缩小右边部分的 View 从左往右移动左边部分 从 0 到 1 透明度增加左边部分。 2. 默认代码配置
2.1 XML 初始布局 norIcon 是左边部分 ViewfocLayout 是右边部分 View。
?xml version1.0 encodingutf-8?
androidx.constraintlayout.widget.ConstraintLayout xmlns:androidhttp://schemas.android.com/apk/res/androidxmlns:apphttp://schemas.android.com/apk/res-autoxmlns:toolshttp://schemas.android.com/toolsandroid:idid/parentandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentandroid:keepScreenOntrueImageViewandroid:idid/norIconandroid:layout_width80dpandroid:layout_height104dpandroid:layout_marginStart24dpandroid:layout_marginBottom24dpandroid:backgrounddrawable/shape_34343a_corner_20dpandroid:contentDescriptionnullandroid:paddingHorizontal24dpandroid:paddingVertical36dpandroid:srcdrawable/ic_camera_video_norapp:layout_constraintBottom_toBottomOfparentapp:layout_constraintStart_toStartOfparent /LinearLayoutandroid:idid/focLayoutandroid:layout_widthwrap_contentandroid:layout_height104dpandroid:layout_marginStart110dpandroid:backgrounddrawable/shape_34343a_corner_20dpandroid:gravitycenterandroid:minWidth200dpandroid:orientationverticalandroid:paddingStart12dpandroid:paddingEnd16dpapp:layout_constraintBottom_toBottomOfid/norIconapp:layout_constraintStart_toStartOfparentImageViewandroid:idid/focIconandroid:layout_width32dpandroid:layout_height32dpandroid:contentDescriptionnullandroid:srcdrawable/ic_camera_picture_foc /com.agg.ui.AGGTextViewandroid:idid/focTextandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_marginTop6dpandroid:gravitycenterandroid:singleLinetrueandroid:textstring/tap_to_photoandroid:textColor#FCC810android:textSize24spapp:UITypefaceBold //LinearLayout
/androidx.constraintlayout.widget.ConstraintLayout
2.2 监听滑动对 View 改变 /*** 往前滑动切换为录像模式/拍照模式*/override fun scrollForward() {if (AnimatorSwitchHelper.isAnimating) {Log.e(TAG, scrollForward: 滑动过快)return}Log.i(TAG, scrollForward: model$mIsVideoModel,isRecordingVideo${isRecording()})if (mIsVideoModel) {if (isRecording()) stopRecord()switchToPhoto()mIsVideoModel falsebinding.tips.text getString(R.string.swipe_forward_to_video_model)binding.norIcon.setImageResource(R.drawable.ic_camera_video_nor)binding.focIcon.setImageResource(R.drawable.ic_camera_picture_foc)binding.focText.text getString(R.string.tap_to_photo)} else {switchToVideo()mIsVideoModel truebinding.tips.text getString(R.string.swipe_forward_to_photo_model)binding.norIcon.setImageResource(R.drawable.ic_camera_picture_nor)binding.focIcon.setImageResource(R.drawable.ic_camera_video_foc)binding.focText.text getString(R.string.tap_to_record)}binding.tips.visibility VISIBLEAnimatorSwitchHelper.startAnimator(binding)} 3. ⚛️ 拍照/录像动效切换实现
3.1 第一阶段动效
1左移右边部分的 View
binding.focLayout.x binding.focLayout.x - 86
2放大右边部分的 View
val defWidth binding.focLayout.width
val focBgBigAnim ValueAnimator.ofInt(defWidth, defWidth 86).apply {addUpdateListener { animation -val width animation.animatedValue as Intval layoutParams binding.focLayout.layoutParams as ViewGroup.LayoutParamslayoutParams.width widthbinding.focLayout.layoutParams layoutParams}}
3.2 第二阶段动效
1动态调整右边部分的约束 第一阶段在 XML 中默认配置的是 layout_constraintStart_toStartOfparent能保证放大时以左边为锚点从左往右放大而第二阶段缩小时需要以右边为锚点此时需要动态改变约束如下
private fun changeConstraint(binding: ActivityMainBinding) {Log.i(TAG, changeConstraint: )val focLayoutId R.id.focLayoutval constraintLayout binding.parentConstraintSet().apply {// 修改约束clone(constraintLayout)// 清除原有的约束clear(focLayoutId, ConstraintSet.START)// 设置新的约束connect(focLayoutId,ConstraintSet.END,ConstraintSet.PARENT_ID,ConstraintSet.END,(binding.focLayout.context.resources.displayMetrics.widthPixels - binding.focLayout.x - binding.focLayout.width - 86).toInt())// 自动播放过渡动画——取消播放与自定义动画重复
// TransitionManager.beginDelayedTransition(constraintLayout)// 应用新的约束applyTo(constraintLayout)}
}
2缩小右边部分的 View
val focBgSmallAnim ValueAnimator.ofInt(defWidth 86, defWidth).apply {addUpdateListener { animation -val width animation.animatedValue as Intval layoutParams binding.focLayout.layoutParams as ViewGroup.LayoutParamslayoutParams.width widthbinding.focLayout.layoutParams layoutParams}addListener(object : AnimatorListenerAdapter() {override fun onAnimationEnd(p0: Animator) {Log.i(TAG, onAnimationEnd: focBgSmallAnim)isAnimating false}})
}
3从左往右移动左边部分
val norBgTransAnim ObjectAnimator.ofFloat(binding.norIcon, translationX, -80f, 0f)
4从 0 到 1 透明度增加左边部分
val norBgAlphaAnim ObjectAnimator.ofFloat(binding.norIcon, alpha, 0f, 1f)
5动画集实现
AnimatorSet().apply {playSequentially(focBgBigAnim, focBgSmallAnim)playTogether(focBgSmallAnim, norBgTransAnim, norBgAlphaAnim)duration 1000start()
}
6还原默认约束 动效做完后需要还原默认约束保证下次动效的正常进行。
if (!isFirstSwitch) restoreConstraint(binding)private fun restoreConstraint(binding: ActivityMainBinding) {Log.i(TAG, restoreConstraint: )val focLayoutId R.id.focLayoutval constraintLayout binding.parentConstraintSet().apply {clone(constraintLayout)clear(focLayoutId, ConstraintSet.END)connect(focLayoutId, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START, 110)applyTo(constraintLayout)}
} 具体动效类的代码参考附录1。 4. ✅ 小结 对于拍照/录像动效切换本文只是一个基础实现方案更多业务细节请参考产品逻辑去实现。 另外由于本人能力有限如有错误敬请批评指正谢谢。 附录1动效帮助类代码
object AnimatorSwitchHelper {private val TAG AnimatorSwitchHelper::class.java.simpleNamevar isAnimating falsevar isFirstSwitch truefun startAnimator(binding: ActivityMainBinding) {Log.i(TAG, startAnimator: isAnimating$isAnimating,isFirstSwitch$isFirstSwitch)isAnimating trueval defWidth binding.focLayout.widthif (!isFirstSwitch) restoreConstraint(binding)if (isFirstSwitch) binding.focLayout.x binding.focLayout.x - 86// 1. 放大Foc的Viewval focBgBigAnim ValueAnimator.ofInt(defWidth, defWidth 86).apply {addUpdateListener { animation -val width animation.animatedValue as Intval layoutParams binding.focLayout.layoutParams as ViewGroup.LayoutParamslayoutParams.width widthbinding.focLayout.layoutParams layoutParams}addListener(object : AnimatorListenerAdapter() {override fun onAnimationEnd(p0: Animator) {Log.i(TAG, onAnimationEnd: focBgBigAnim)// 为绘制反向动画需修改约束方向changeConstraint(binding)isFirstSwitch false}})}// 2.1 缩小Foc的Viewval focBgSmallAnim ValueAnimator.ofInt(defWidth 86, defWidth).apply {addUpdateListener { animation -val width animation.animatedValue as Intval layoutParams binding.focLayout.layoutParams as ViewGroup.LayoutParamslayoutParams.width widthbinding.focLayout.layoutParams layoutParams}addListener(object : AnimatorListenerAdapter() {override fun onAnimationEnd(p0: Animator) {Log.i(TAG, onAnimationEnd: focBgSmallAnim)isAnimating false}})}// 2.2 从左往右移动Nor的Viewval norBgTransAnim ObjectAnimator.ofFloat(binding.norIcon, translationX, -80f, 0f)// 2.3 透明度渐显Nor的Viewval norBgAlphaAnim ObjectAnimator.ofFloat(binding.norIcon, alpha, 0f, 1f)AnimatorSet().apply {playSequentially(focBgBigAnim, focBgSmallAnim)playTogether(focBgSmallAnim, norBgTransAnim, norBgAlphaAnim)duration 1000start()}}private fun changeConstraint(binding: ActivityMainBinding) {Log.i(TAG, changeConstraint: )val focLayoutId R.id.focLayoutval constraintLayout binding.parentConstraintSet().apply {// 修改约束clone(constraintLayout)// 清除原有的约束clear(focLayoutId, ConstraintSet.START)// 设置新的约束connect(focLayoutId,ConstraintSet.END,ConstraintSet.PARENT_ID,ConstraintSet.END,(binding.focLayout.context.resources.displayMetrics.widthPixels - binding.focLayout.x - binding.focLayout.width - 86).toInt())// 自动播放过渡动画——取消播放与自定义动画重复
// TransitionManager.beginDelayedTransition(constraintLayout)// 应用新的约束applyTo(constraintLayout)}}private fun restoreConstraint(binding: ActivityMainBinding) {Log.i(TAG, restoreConstraint: )val focLayoutId R.id.focLayoutval constraintLayout binding.parentConstraintSet().apply {clone(constraintLayout)clear(focLayoutId, ConstraintSet.END)connect(focLayoutId, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START, 110)applyTo(constraintLayout)}}}