文章目录:
蓝月羽:Android知识点文章目录这篇我们来学习一下自定义View,实现一下有趣的动画效果,就是滚动视图,然后子视图按照设定的动画,进入屏幕。效果图:
演示效果https://www.zhihu.com/video/1506245364269678592ScrollChildMountAnimView :用于包裹普通子视图来完成动画的视图(偷梁换柱)
ScrollAnimChildContainerLayout :滚动动画子视图的容器
MountAnimScrollView :挂载动画的滚动视图
持有关系:
MountAnimScrollView -》ScrollAnimChildContainerLayout -》MountAnimScrollView
ScrollAnimMountCallback :滚动视图子视图动画挂载回调, 被 ScrollChildMountAnimView 实现
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 挂载动画属性-->
<declare-styleable name="ScrollChildMountAnimView_LayoutParams">
<!-- 透明度动画-->
<attr name="mount_anim_alpha" format="boolean" />
<!-- 缩放x动画-->
<attr name="mount_anim_scaleX" format="boolean" />
<!-- 缩放y动画-->
<attr name="mount_anim_scaleY" format="boolean" />
<!-- 背景颜色渐变动画开始值-->
<attr name="mount_anim_fromBgColor" format="color" />
<!-- 背景颜色渐变动画结束值-->
<attr name="mount_anim_toBgColor" format="color" />
<!-- 平移动画-->
<attr name="mount_anim_translation" />
</declare-styleable>
<!-- 属性 mount_anim_translation 的可选值-->
<attr name="mount_anim_translation">
<!-- 平移动画从头部进入-->
<flag name="fromTop" value="0x01" />
<!-- 平移动画从底部进入-->
<flag name="fromBottom" value="0x02" />
<!-- 平移动画从左边进入-->
<flag name="fromLeft" value="0x04" />
<!-- 平移动画从右边进入-->
<flag name="fromRight" value="0x08" />
</attr>
</resources>
public interface ScrollAnimMountCallback {
/**
* 子视图动画挂载(滑动的时候会触发该方法)
*
* @param ratio 动画的比例 (0~1)
*/
void onChildAnimMount(float ratio);
/**
* 子视图动画卸载(就是恢复视图原来的状态)
*/
void onChildAnimUnmount();
}
用于包裹普通子视图来完成动画的视图(偷梁换柱),实现了 ScrollAnimMountCallback
具体代码:ScrollChildMountAnimView.java
3.1)在 onSizeChanged 方法进行宽高变量的赋值和重置视图
/**
* 当视图的大小发生变化时,在布局期间调用。如果你刚刚被添加到视图层次结构中,你被调用时的旧值为0。
*
* @param w 当前的视图宽度
* @param h 当前视图的高度
* @param oldw 当前视图旧的宽度
* @param oldh 当前视图旧的高度
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
currentWidth = w;
currentHeight = h;
onChildAnimUnmount();
}
3.2)在 onChildAnimMount 方法,进行视图的相关动画属性设置
@Override
public void onChildAnimMount(float ratio) {
// 执行视图动画
// ratio:0~1
//控制自身的动画属性
if (isMountAnimAlpha) {
setAlpha(ratio);
}
if (isMountAnimScaleX) {
setScaleX(ratio);
}
if (isMountAnimScaleY) {
setScaleY(ratio);
}
//判断到底是哪一种值:fromTop,fromBottom,fromLeft,fromRight
if (isMountAnimFrom(TRANSLATION_FROM_BOTTOM)) {
setTranslationY(currentHeight * (1 - ratio)); // currentHeight ---> 0 代表原来的位置
}
if (isMountAnimFrom(TRANSLATION_FROM_TOP)) {
setTranslationY(-currentHeight * (1 - ratio)); // -currentHeight ---> 0 代表原来的位置
}
if (isMountAnimFrom(TRANSLATION_FROM_LEFT)) {
setTranslationX(currentWidth * (1 - ratio));// currentWidth ---> 0 代表原来的位置
}
if (isMountAnimFrom(TRANSLATION_FROM_RIGHT)) {
setTranslationX(-currentWidth * (1 - ratio));// -currentWidth ---> 0 代表原来的位置
}
// 颜色渐变动画
if (mountAnimFromBgColor != -1 && mountAnimToBgColor != -1) {
//ratio=0.5 color=中间颜色
setBackgroundColor((Integer) argbEvaluator.evaluate(ratio, mountAnimFromBgColor, mountAnimToBgColor));
}
}
滚动动画子视图的容器,这里会为布局中的普通子视图,包裹上 ScrollChildMountAnimView ,起到偷梁换柱的效果,进而实现动画
具体代码:ScrollAnimChildContainerLayout.java
4.1)定义 ScrollAnimLayoutParams ,读取自定义属性
public static class ScrollAnimLayoutParams extends LinearLayoutCompat.LayoutParams {
public int mountAnimFromBgColor;//背景颜色变化开始值
public int mountAnimToBgColor;//背景颜色变化结束值
public boolean isMountAnimAlpha;//是否需要透明度动画
public int mountAnimTranslation;//平移值
public boolean isMountAnimScaleX;//是否需要x轴方向缩放
public boolean isMountAnimScaleY;//是否需要y轴方向缩放
public ScrollAnimLayoutParams(Context context, AttributeSet attrs) {
super(context, attrs);
// 从child里面拿到我自定义的属性
@SuppressLint("CustomViewStyleable")
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ScrollChildMountAnimView_LayoutParams);
mountAnimFromBgColor = typedArray.getInt(R.styleable.ScrollChildMountAnimView_LayoutParams_mount_anim_fromBgColor, -1);
mountAnimToBgColor = typedArray.getInt(R.styleable.ScrollChildMountAnimView_LayoutParams_mount_anim_toBgColor, -1);
isMountAnimAlpha = typedArray.getBoolean(R.styleable.ScrollChildMountAnimView_LayoutParams_mount_anim_alpha, false);
mountAnimTranslation = typedArray.getInt(R.styleable.ScrollChildMountAnimView_LayoutParams_mount_anim_translation, -1);
isMountAnimScaleX = typedArray.getBoolean(R.styleable.ScrollChildMountAnimView_LayoutParams_mount_anim_scaleX, false);
isMountAnimScaleY = typedArray.getBoolean(R.styleable.ScrollChildMountAnimView_LayoutParams_mount_anim_scaleY, false);
typedArray.recycle();
}
/**
* 释放需要挂载动画
*
* @return true: 需要 false:不需要
*/
public boolean isNeedMountAnim() {
return isMountAnimAlpha ||
isMountAnimScaleX ||
isMountAnimScaleY ||
mountAnimTranslation != -1 ||
(mountAnimFromBgColor != -1 && mountAnimToBgColor != -1);
}
}
4.2)重载 generateLayoutParams 方法
当前方法会在 LayoutInflater.from(getContext()).inflate 中被调
/**
* 参考:https://blog.csdn.net/wjr1949/article/details/105607740
* 当前方法会被 LayoutInflater.from(getContext()).inflate 中 的 tryInflatePrecompiled 进行调用
*
* @param attrs 属性集合
*/
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new ScrollAnimLayoutParams(getContext(), attrs);
}
4.3)重载 addView 方法,进行偷梁换柱
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
if (params instanceof ScrollAnimLayoutParams) {
ScrollAnimLayoutParams layoutParams = (ScrollAnimLayoutParams) params;
if (layoutParams.isNeedMountAnim()) {
ScrollChildMountAnimView newChild = generateAnimView(layoutParams);
// 将原本的视图包进需要执行动画的视图
newChild.addView(child);
super.addView(newChild, index, params);
} else {
// 不需要挂载动画
super.addView(child, index, params);
}
} else {
super.addView(child, index, params);
}
}
/**
* 生成动画视图
*
* @param params 视图的 LayoutParams
*/
private ScrollChildMountAnimView generateAnimView(ScrollAnimLayoutParams params) {
ScrollChildMountAnimView view = new ScrollChildMountAnimView(getContext());
view.setMountAnimFromBgColor(params.mountAnimFromBgColor);
view.setMountAnimToBgColor(params.mountAnimToBgColor);
view.setMountAnimScaleX(params.isMountAnimScaleX);
view.setMountAnimScaleY(params.isMountAnimScaleY);
view.setMountAnimAlpha(params.isMountAnimAlpha);
view.setMountAnimTranslation(params.mountAnimTranslation);
return view;
}
挂载动画的滚动视图,这里是真正做动画驱动的类
5.1)重载 onFinishInflate 方法,获取 ScrollAnimChildContainerLayout,当前方法也是在 LayoutInflater.from(getContext()) 中被调用的
// 在 LayoutInflater.from(getContext()) 中被调
@Override
protected void onFinishInflate() {
super.onFinishInflate();
containerLayout = (ScrollAnimChildContainerLayout) getChildAt(0);
}
5.2)重载 onSizeChanged 方法,将第一个视图设置为全屏
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// 将第一个视图的高度设置为 ScrollView 的高度
View firstChild = containerLayout.getChildAt(0);
firstChild.getLayoutParams().height = getHeight();
}
5.3)重载 onScrollChanged 方法,去调用 ScrollAnimMountCallback 的 onChildAnimMount 和 onChildAnimUnmount 方法,从而实现动画加载和恢复
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
// 滚动监听
int scrollViewHeight = getHeight();
int childCount = containerLayout.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = containerLayout.getChildAt(i);
if (child instanceof ScrollAnimMountCallback) {
dispatchAnim(child, scrollViewHeight, t);
}
}
}
/**
* 分发动画
*
* @param child 子视图
* @param scrollViewHeight ScrollView 的高度
* @param t 当前垂直滚动原点
*/
private void dispatchAnim(View child, int scrollViewHeight, int t) {
ScrollAnimMountCallback scrollAnimMountCallback = (ScrollAnimMountCallback) child;
//1.child离scrollview顶部的高度 a
int distanceTop = child.getTop();
int distanceHeight = child.getHeight();
//2.得到scrollview滑出去的高度 b 就是int t,
//3.得到child离屏幕顶部的高度 c
int distanceAbsoluteTop = distanceTop - t;
//什么时候执行动画?当child滑进屏幕的时候
if (distanceAbsoluteTop <= scrollViewHeight) {
int visibleGap = scrollViewHeight - distanceAbsoluteTop;
//确保ratio是在0~1,超过了1 也设置为1
scrollAnimMountCallback.onChildAnimMount(clamp(visibleGap / (float) distanceHeight, 1f, 0f));
} else {//否则,就恢复到原来的位置
scrollAnimMountCallback.onChildAnimUnmount();
}
}
具体查看:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<com.young.scrollchildanim.MountAnimScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:mountAnim="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.young.scrollchildanim.ScrollAnimChildContainerLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="600dp"
android:background="@android:color/white"
android:fontFamily="serif"
android:gravity="center"
android:padding="25dp"
android:text="公司面临着一项重大抉择,现在将进行一次我们的世纪大会,董事长已经各位股东各就各位。"
android:textColor="@android:color/black"
android:textSize="25sp"
tools:visibility="gone" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/meeting"
mountAnim:mount_anim_alpha="true"
android:background="#FF0000"/>
<View
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#007788"
mountAnim:mount_anim_alpha="true" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="200dp"
android:layout_height="220dp"
android:src="@drawable/boss"
mountAnim:mount_anim_alpha="true"
mountAnim:mount_anim_translation="fromLeft|fromBottom" />
<View
android:layout_width="match_parent"
android:layout_height="200dp"
mountAnim:mount_anim_fromBgColor="#ffff00"
mountAnim:mount_anim_toBgColor="#88EE66" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="220dp"
android:layout_height="310dp"
android:layout_gravity="right"
android:src="@drawable/boss"
mountAnim:mount_anim_translation="fromRight" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="serif"
android:gravity="center"
android:padding="20dp"
android:text="辛苦遭逢起一经,干戈寥落四周星。
山河破碎风飘絮,身世浮沉雨打萍。
惶恐滩头说惶恐,零丁洋里叹零丁。
人生自古谁无死,留取丹心照汗青。"
android:textSize="23sp"
mountAnim:mount_anim_alpha="true"
mountAnim:mount_anim_translation="fromBottom" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_gravity="center"
android:layout_margin="20dp"
android:src="@drawable/applause"
mountAnim:mount_anim_scaleX="true"
mountAnim:mount_anim_scaleY="true" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="20dp"
android:src="@drawable/xiemu"
mountAnim:mount_anim_translation="fromLeft|fromBottom" />
</com.young.scrollchildanim.ScrollAnimChildContainerLayout>
</com.young.scrollchildanim.MountAnimScrollView>
面试是每个求职者都要经历的一个重要环节。特别是对于Android测试岗位的面试,面试官通常会通过一系列的问题来评估候选人的技术能力和经验。为了帮助大家更好地准备Android测试岗位的面试,本文整理了一些常见的Android测试岗位面试题,供大家参考。
1. 什么是Android测试?
Android测试是指在Android平台上进行软件测试的过程,包括对Android应用的功能、性能和稳定性进行验证和评估。
2. Android测试的重要性是什么?
Android测试对于保障应用的质量和稳定性非常重要。它可以发现应用的潜在问题和缺陷,提高用户体验,减少后期修复成本。
3. Android测试中的黑盒测试和白盒测试有什么区别?
黑盒测试是指基于应用的外部功能进行测试,不需要了解应用的内部实现细节。而白盒测试是指基于应用的内部实现细节进行测试,需要了解应用的代码结构和逻辑。
1. 你在Android平台上进行过哪些测试?
回答这个问题时,可以列举自己在以往项目中进行过的各种测试类型,例如功能测试、性能测试、兼容性测试等。
2. 你如何进行Android应用的功能测试?
在功能测试中,可以通过编写测试用例,模拟用户的操作场景,对应用的各项功能进行验证。可以使用JUnit框架进行单元测试,使用Espresso框架进行UI测试。
3. 如何进行Android应用的性能测试?
性能测试主要关注应用在不同情况下的响应速度和资源消耗情况。可以使用工具如Android Studio提供的Profiler来监测应用的内存、CPU和网络使用情况。
1. 在测试过程中遇到过哪些常见问题?如何解决?
回答这个问题时,可以提到一些常见的问题,比如应用崩溃、性能下降、兼容性问题等。可以通过分析日志、重现问题、进行代码调试等方式来解决。
2. 如何处理Android应用的兼容性问题?
在处理兼容性问题时,可以先分析问题出现的具体场景和条件,然后根据不同的Android版本和设备特性进行适配和调试。
3. 在测试过程中如何保障数据的安全性?
对于涉及用户隐私和敏感数据的应用,保障数据的安全性尤为重要。可以采用数据加密、访问权限控制、网络传输加密等方式来保护数据的安全。
1. 如何与开发团队有效合作?
与开发团队有效合作的关键是建立良好的沟通和协作机制。可以定期开会、交流测试计划和结果,及时报告和解决问题,保持良好的沟通和合作。
2. 如何处理与产品经理的分歧?
在与产品经理存在分歧时,可以通过数据和实验证据来支持自己的观点,并积极参与讨论和沟通,达成共识。
3. 在团队中遇到合作困难时,你如何解决?
在团队中遇到合作困难时,可以积极倾听别人的意见和建议,主动沟通解决问题,互相支持和配合,共同解决困难。
通过本文的介绍,我们了解了Android测试岗位的一些面试题目。在准备面试时,我们不仅要对Android测试的基础知识有所了解,还要具备一定的技术能力和解决问题的能力,同时注重团队合作能力。希望大家能够通过这些面试题目的准备,更好地展示自己的优势,顺利通过Android测试岗位的面试。
动了我的情
词曲:郭玲
演唱:郭玲
是你动了我的情 哎哎呦
动动动动我的心 啦啦啦
跳跳跳跳跳不停
哎呀呀哎呀呀 啦啦啦啦
我们还没有见面 感觉到你要出现
感觉你就在我的身边
我们距离有多远 什么时候能见面
感觉真的很灵验
是你动了我的情 波动了我的心
习惯听到你的声音
是你动了我的情 带走了我的心
我们相爱永远到是最深
动动动动我的心 跳跳跳跳跳不停
原来真的爱上了你
动动动动我的心 跳跳跳跳跳不停
跟你在一起忘了我自己
动 动 动 动我的心
跳 跳 跳 跳 跳不停
原来真的爱上了你
动 动 动 动我的心
跳 跳 跳 跳 跳不停
哦爱情真的让人很着迷
我们距离有多远
什么时候能见面
感觉真的很灵验
是你动了我的情
温暖了我的心
喜欢和你一起看电影
是你动了我的情
付出了我真心
什么也挡不住缘分来临
RAP:我们还没有见面
感觉你就要出现
感觉你就在我的身边
我们距离有多远
什么时候能见面
感觉真的好好灵验噢
动 动 动 动 我的心
跳 跳 跳 跳 跳不停
原来真的爱上了你
动 动 动 动我的心
跳 跳 跳 跳 跳不停
跟你在一起忘了我自己
动 动 动 动我的心
跳 跳 跳 跳 跳不停
原来真的爱上了你
动 动 动 动我的心
跳 跳 跳 跳 跳不停
什么也挡不住缘分来临
动 动 动 动 我的心
跳 跳 跳 跳 跳不停
原来真的爱上了你
动 动 动 动我的心
跳 跳 跳 跳 跳不停
跟你在一起忘了我自己
呜呀呀呀
哦咿呀咿呀
哦什么也挡不住缘分的来临
动动动动我的心
根据我多年看歌词猜歌经验一定是Es Rappelt Im Karton,如果我说对了请给我点赞。
如果错了希望题主下次写歌词求歌的时候不要打标点,因为那个逗号影响了我90%的功力《动动小手动动小脚》是一首经典的儿歌,它鼓励孩子们积极参与动作。歌词简单易懂,旋律欢快动听。通过唱歌和跳舞,孩子们可以锻炼身体,培养协调性和节奏感。
这首儿歌不仅能够增强孩子们的体能,还能够激发他们的想象力和创造力。同时,它也是一种亲子互动的方式,家长可以和孩子一起唱唱跳跳,增进亲子关系。总之,这首儿歌是孩子们成长过程中的一份美好回忆,也是他们快乐童年的一部分。
2003年10月,Andy Rubin等人创建Android公司,并组建Android团队。
2005年8月17日,Google低调收购了成立仅22个月的高科技企业Android及其团队。安迪鲁宾成为Google公司工程部副总裁,继续负责Android项目。
2007年11月5日,谷歌公司正式向外界展示了这款名为Android的操作系统,并且在这天谷歌宣布建立一个全球性的联盟组织,该组织由34家手机制造商、软件开发商、电信运营商以及芯片制造商共同组成。
并与84家硬件制造商、软件开发商及电信营运商组成开放手持设备联盟来共同研发改良Android系统,这一联盟将支持谷歌发布的手机操作系统以及应用软件,Google以Apache免费开源许可证的授权方式,发布了Android的源代码。
2008年,在GoogleI/O大会上,谷歌提出了AndroidHAL架构图,在同年8月18号,Android获得了美国联邦通信委员会(FCC)的批准,在2008年9月,谷歌正式发布了Android 1.0系统,这也是Android系统最早的版本。
心跳跳爱动动
作曲:林伟文
作词:柳佳佳
演唱:柳佳佳
编曲:熊光焰 林伟文
录音 混音:林伟文 吕汉钊
说声爱你爱你永久
我拨通电话想对你说开不了口
说声想你想到发呆
说声一心一意一生一世陪伴你
现实的世界让我纠结
面包与爱情之间如何选择
大声对你说 I LOVE YOU
只想说爱你爱你直到永远
心跳跳爱动动
我一分一秒一分一秒放纵自己
心跳跳爱动动
爱你不需不要不需不要什么理由
说声爱你爱你永久
我拨通电话想对你说开不了口
说声想你想到发呆
说声一心一意一生一世陪伴你
现实的世界让我纠结
面包与爱情之间如何选择
大声对你说 I LOVE YOU
只想说爱你爱你直到永远
心跳跳爱动动
我一分一秒一分一秒放纵自己
心跳跳爱动动
爱你不需不要不需不要什么理由
心跳跳爱动动
我一分一秒一分一秒放纵自己
心跳跳爱动动
爱你不需不要不需不要什么理由
现实的世界让我纠结
面包与爱情之间如何选择
大声说爱你
心跳跳爱动动
两个人世界更精彩
答:蠢蠢欲动。
详细解释:
发音:chǔn chǔn yù dònɡ
释义:
蠢蠢:爬虫蠕动的样子。形容像虫子一样开始动弹。比喻敌人策划准备进攻;或坏人准备捣乱破坏。
扩展资料:
出处:
南朝 宋 刘敬叔《异苑 句容水脉》:“掘得一黑物,无有首尾,形如数百斛舡,长数十丈,蠢蠢而动。”
例句:
正如她所预料的,兽人们已经蠢蠢欲动了。
近义:
跃跃欲试
1、打开flash 软件,点击我的文档,打开工作界面。点击属性面板,把编辑界面的颜色为黑色。左键对准矩形工具,按住不动,这时候就出现一个小工具面板,在里面选择“多角星形工具”。在属性面板里找到<<选项>>.然后点击选项,多边形改成《星形》。《星形顶角大小》改成《0.20>.《边数》改成《4》。颜色改成《放射状》。颜色为灰色。在编辑区内画一个,4变形的星形。
2、画完以后,点击第一帧再点击上面的《修改》《分离》然后点击第十帧插入关键帧。同样点击修改--分离。然后调整透明度为零。
3、再点击第20帧,右键点击插入关键帧,同样点击修改--分离,调整透明度为100.。然后点击第10帧,添加形状补间。点击第20帧,添加形状补间动画。然后测试影片,保存为jif动画。
4、点击第5帧,在属性面板,《补间》里点击形状补间。再点击第15帧,在下面的《补间》里点击形状补间。然后点击《控制》测试影片,保存为gif 动画。
劳动可以作为名词,如劳动是光荣的。也可以作为动词,如大人们都在地里劳动