android的md动画,Android-notes/动画体系详解.md at master · drs0214/Android-notes · GitHub

Android 动画详解:属性动画、View 动画和帧动画

在 Android 中,基本的动画共有三种类型:

View 动画:也叫视图动画或者补间动画,主要是指 android.view.animation 包下面的一些类,只能被用来设置给 View,缺点是比如当控件移动之后,接收点击的控件的位置不会跟随移动,并且能够实现的效果只有移动、缩放、旋转和淡入淡出操作四种及其组合。

Drawable 动画:也叫 Frame 动画或者帧动画,其实可以划分到视图动画的类别,实现方式是将一些列的 Drawable 像幻灯片一样一个一个地显示。

Property 动画: 属性动画主要是指 android.animation 包下面的一些类,只对 API 11 以上版本的Android 系统才有效,但我们可以通过兼容库做低版本兼容。这种动画可以设置给任何 Object,包括那些还没有渲染到屏幕上的对象。这种动画是可扩展的,可以让你自定义任何类型和属性的动画。

1、Drawable 动画

在这里,我们先对 Drawable 动画进行讲解,因为它相对于后面的两种动画比较简单。在示例程序我们准备了一系列图片资源,并在 drawable 文件夹下面定义了动画资源 record_anim.xml:

xmlns:android="http://schemas.android.com/apk/res/android">

然后,我们在代码中使用该资源,并将其赋值给 ImageView。然后,我们从该控件中获取该 Drawable 并将其转换成 AnimationDrawable,随后我们调用它的 start() 方法就开启了 Drawable 动画:

getBinding().ivRecord.setImageResource(R.drawable.record_anim);

animDraw = (AnimationDrawable) getBinding().ivRecord.getDrawable();

animDraw.start();

此外,我们可以调用该 Drawable 的 stop() 方法停止动画。

帧动画的注意事项

使用帧动画的时候要注意设置的图片不宜过多、过大,以防止因为内存不够而出现 OOM。

2、View 动画

2.1 基本 View 动画

该动画的资源处在 android.view.animation 包下,主要有以下几个类,它们都继承自 Animation ,我们可以使用它们来实现复杂的动画。这些动画类分别有对应的 xml 标签,所以,我们可以在 xml 中定义动画,也可以在代码中实现动画效果。这里的 AnimationSet 可以用来将多个动画效果进行组合,各预定义动画的对照可以参考下面这张图表:

View%E5%8A%A8%E7%94%BB%E6%A1%86%E6%9E%B6.png

2.2 View 动画属性

当然,要实现一种动画效果会有许多属性需要指定,在 xml 中,我们用标签的属性指定,在代码中我们用对象的 setter 方法指定。于是,我们可以得到下面这个对应关系:

View%E5%8A%A8%E7%94%BB%E5%B1%9E%E6%80%A7%E8%AF%A6%E8%A7%A3.png

上面的对应关系是所有的 View 动画共用的,对各个具体的动画类型还有其独有的属性。你可以在各个动画的构造方法中,通过它们从 AttributeSet 中获取了哪些字段来了解它们都定义了哪些属性,这里我们不对其一一进行说明。各预定义的属性动画分别按照不同的方式实现了 Animation 的 applyTransformation 方法,具体的这些属性如何使用以及 View 动画的效果是如何实现的,都可通过阅读该方法的定义得知。

对于 AnimationSet,它内部维护了一个 Animation 列表,并且其本身也是一个 Animation,所以,AnimationSet 内部可以添加子 AnimationSet。

2.3 插值器

上文中我们提到过,View 动画的具体实现是通过覆写 Animation 的 applyTransformation 方法来完成的。这里我们以 AlphaAnimation 为例来看它是如何作用的,同时你应该注意插值器的作用原理。该方法会在 Animation 中被循环调用,调用的时候会根据插值器计算出一个时间,并将其传递到 applyTransformation 方法中。

Animation 的 getTransformation 方法片段:

if ((normalizedTime >= 0.0f || mFillBefore) && (normalizedTime <= 1.0f || mFillAfter)) {

if (!mStarted) {

fireAnimationStart();

mStarted = true;

if (NoImagePreloadHolder.USE_CLOSEGUARD) {

guard.open("cancel or detach or getTransformation");

}

}

if (mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);

if (mCycleFlip) {

normalizedTime = 1.0f - normalizedTime;

}

final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);

applyTransformation(interpolatedTime, outTransformation);

}

AlphaAnimation 的 applyTransformation 方法:

protected void applyTransformation(float interpolatedTime, Transformation t) {

final float alpha = mFromAlpha;

t.setAlpha(alpha + ((mToAlpha - alpha) * interpolatedTime));

}

显然,这里的 interpolatedTime 的是一个比例。比如,假如一个透明动画需要持续 10s,透明度需要从 0.5f 到 1.0f,而插值的规则是一个二次函数。那么第 t (0

alpha = 0.5f + (1.0f - 0.5f) * t^2 / 100

以上就是插值器的作用原理,你也可以按照自己的需求实现自己的插值器,从而实现期待的动画效果。

2.4 使用 View 动画

作为一个例子,这里我们实现一个让控件抖动的动画。在 anim 文件夹下面,我们定义一个平移的动画,并使用插值器使其重复:

anim/shake.xml 的定义:

android:duration="700"

android:fromXDelta="0.0"

android:interpolator="@anim/cycle_7"

android:toXDelta="15.0" />

插值器 anim/cicle_7.xml 的定义:

android:cycles="4.0" />

然后,我们在代码中加载 Animation 并调用控件的 startAnimation() 方法开启动画:

getBinding().v.startAnimation(AnimationUtils.loadAnimation(this, R.anim.shake));

对于 View ,我们有 startAnimation() 用来对 View 开始动画;有 clearAnimation() 用来取消 View 在执行的动画。

不使用 xml,仅使用代码我们一样可以实现上述的效果,这里我们不再进行说明。

2.5 View 动画的特殊使用场景

2.5.1 LayoutAnimation

LayoutAnimation 作用于 ViewGroup,可以使其子元素出场时都均有某种动画效果,通常用于 ListView。我们可以像下面这样定义布局动画:

android:delay="500"

android:animation="@anim/shake"

xmlns:android="http://schemas.android.com/apk/res/android" />

显然,这里我们需要引用一个其他的动画。然后,我们可以在 ListView 的 layoutAnimation 属性中指定布局动画。或者调用 ListView 的 setLayoutAnimation() 方法应用上述动画。

2.5.2 Activity 切换

我们可以通过在 Activity 中调用 overridePendingTransition(R.anim.shake, R.anim.shake); 方法来重写 Activity 的切换动画。注意这个方法应该在 startActivity(Intent) 或者 finish() 之后立即调用。

3、属性动画

3.1 基础梳理

我们可以对比 View 动画来学习属性动画。

属性动画主要是指 android.animation 包下面的一些类。

属性动画基础的动画类是 Animator;属性动画也为我们提供了几个预定义的类:AnimatorSet, ObjectAnimator, TimeAnimator 和 ValueAnimator;这几个预定义类之间的继承关系是,AnimatorSet 和 ValueAnimator 直接继承自 Animator,而 ObjectAnimator 和 TimeAnimator 继承自 ValueAnimator。

与 View 动画不同的是,属性动画的使用范围更加宽泛,它不局限于 View,本质上它是通过修改控件的属性值实现的动画。当你尝试对某个对象的某个属性进行修改的时候会有一些限制,即属性动画要求该对象必须提供了该属性的 setter 方法。

属性动画也有 xml 和代码两种定义方式,它的 xml 通常定义在 animator 文件夹下面,而 View 动画定义在 anim 文件夹下面。

属性动画提供了类似于 AnimationUtils 的方法用来从布局文件夹中加载属性动画:AnimatorInflater 类的 loadAnimator() 方法。

属性动画也有自己的插值器:TimeInterpolator,并且也提供了几个预定义的插值器。

我们也可以调用 View 的方法来使用属性动画,我们可以通过 View 的 animate() 方法获取一个 ViewPropertyAnimator,然后调用 ViewPropertyAnimator 的其他方法进行链式调用以实现复杂的属性动画效果。

下面是属性动画的代码实现和 xml 实现两种方式的对比:

%E5%B1%9E%E6%80%A7%E5%8A%A8%E7%94%BB.png

上文中,我们总结了属性动画的一些知识,并将其与 View 动画进行了对比。这里是一个简单的梳理,在下文中我们会对属性动画进行更加详细的介绍。

3.2 使用属性动画

3.2.1 ValueAnimator

上面说过 ValueAnimator 是 ObjectAnimator 和 TimeAnimator 的基类,我们可以这样使用它:

ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);

anim.setDuration(300);

anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

float currentValue = (float) animation.getAnimatedValue();

Log.d("TAG", "cuurent value is " + currentValue);

}

});

anim.start();

这里我们使用 log 输出了值渐变的过程,从日志中可以看出它的效果是值从 0 不断递增直到 1。如果我们在这个监听方法中根据值修改控件的属性一样可以实现动画效果。除了 ofFloat() 还有 ofInt() 等方法,它们的效果相似。

3.2.2 ObjectAnimator

上面,如果我们想要实现动画效果,需要在 ValueAnimator 的监听事件中修改对象的属性,这里的 ObjectAnimator ,我们只需要传入对象实例和属性的字符串名称,修改对象属性的操作就可以自动完成。比如下面的程序的效果是控件 textview 的透明度会在 5s 之内从 1 变成 0 再变回 1.

ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);

animator.setDuration(5000);

animator.start();

注意这里我们传入的是 alpha,这个字段本身并不存在于控件中,而是有一个 setAlpha() 的方法。也就是说,ObjectAnimator 作用的原理是通过反射触发 setter 方法而不是修改属性来实现的。你可以在类 PropertyValuesHolder 中更详细地了解这方面的内容。

PropertyValuesHolder 包装了我们要修改的属性的对象和方法等信息,然后会使用反射触发指定对象的方法来完成对对象属性的修改。其中

void setupSetter(Class targetClass) {

Class> propertyType = mConverter == null ? mValueType : mConverter.getTargetType();

mSetter = setupSetterOrGetter(targetClass, sSetterPropertyMap, "set", propertyType);

}

会去寻找我们要修改属性的 setter 方法,然后

void setAnimatedValue(Object target) {

if (mProperty != null) {

mProperty.set(target, getAnimatedValue());

}

if (mSetter != null) {

try {

mTmpValueArray[0] = getAnimatedValue();

mSetter.invoke(target, mTmpValueArray);

} catch (InvocationTargetException e) {

Log.e("PropertyValuesHolder", e.toString());

} catch (IllegalAccessException e) {

Log.e("PropertyValuesHolder", e.toString());

}

}

}

会去触发 setter 方法,以修改对象的属性。

3.2.3 AnimatorSet

AnimatorSet 内部提供了一个构建者 AnimatorSet.Builder 来帮助我们构建组合动画,AnimatorSet.Builder 提供了下面四种方法:

after(Animator anim):将现有动画插入到传入的动画之后执行

after(long delay):将现有动画延迟指定毫秒后执行

before(Animator anim):将现有动画插入到传入的动画之前执行

with(Animator anim):将现有动画和传入的动画同时执行

当我们调用 AnimatorSet 的 play() 方法的时候就能获取一个 AnimatorSet.Builder 实例,然后我们就可以使用构建者的方法进行链式调用了:

ObjectAnimator moveIn = ObjectAnimator.ofFloat(textview, "translationX", -500f, 0f);

ObjectAnimator rotate = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);

ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);

AnimatorSet animSet = new AnimatorSet();

animSet.play(rotate).with(fadeInOut).after(moveIn);

animSet.setDuration(5000);

animSet.start();

3.2.4 TypeEvaluator

正如前文所述,属性动画也有自己的插值器,我们可以通过插值函数指定在某个时间段内属性改变的速率。插值函数得到的是一个比例,是没有意义的。在 View 动画的 AlphaAnimation 中,如果我们指定了起止的透明度,那么我们可以通过透明度的计算规则得到某个时刻的透明度。但是对于属性动画,因为它可以应用于任何属性,这个属性又可能是任何类型的,那么这个属性将采用什么样的计算规则呢?这就需要我们使用 TypeEvaluator 来指定一个计算规则。也就是说,TypeEvaluator 是属性动画的属性的计算规则。

下面是 TypeEvaluator 的定义,这里的三个参数的含义分别是,fraction 是当前的比例,可以通过插值器计算得到;startValue 和 endValue 分别是属性变化的起止值。它的返回结果就是在某个时刻某个属性的值。

public interface TypeEvaluator {

public T evaluate(float fraction, T startValue, T endValue);

}

属性动画中已经为我们提供了几个预定义的 TypeEvaluator,比如 FloatEvaluator:

public class FloatEvaluator implements TypeEvaluator {

public Float evaluate(float fraction, Number startValue, Number endValue) {

float startFloat = startValue.floatValue();

return startFloat + fraction * (endValue.floatValue() - startFloat);

}

}

在属性动画的 PropertyValuesHolder 中会根据属性的类型选择预定义的 TypeEvaluator。但是如果我们的属性的类型不在预定义的范围之内就需要自己实现一个 TypeEvaluator。下面我们以日期类型为例来实现一个 TypeEvaluator。

当我们使用 ValueAnimator 的 ofObject() 方法获取 ValueAnimator 实例的时候,要求我们传入一个 TypeEvaluator,于是我们可以像下面这样定义:

private static class DateEvaluator implements TypeEvaluator {

@Override

public Date evaluate(float fraction, Date startValue, Date endValue) {

long startTime = startValue.getTime();

return new Date((long) (startTime + fraction * (endValue.getTime() - startTime)));

}

}

然后,我们可以这样使用它:

ValueAnimator animator = ValueAnimator.ofObject(new DateEvaluator(), new Date(0), new Date());

animator.setDuration(5000);

animator.addUpdateListener(animation -> {

Date date = (Date) animation.getAnimatedValue();

LogUtils.d(date);

});

animator.start();

这样就可以得到在 5s 之内输出的从时间戳为0,到当前时刻的所有的日期变化。

3.2.5 TimeInterpolator

就像 View 动画一样,我们可以为属性动画指定一个插值器。插值器的作用是用来设置指定时间段内数值的变化的速率。在属性动画中,插值器是 TimeInterpolator,同样也有几个默认的实现:

AccelerateDecelerateInterolator:先加速后减速。

AccelerateInterpolator:加速。

DecelerateInterpolator:减速。

AnticipateInterpolator:先向相反方向改变一段再加速播放。

AnticipateOvershootInterpolator:先向相反方向改变,再加速播放,会超出目标值然后缓慢移动至目标值,类似于弹簧回弹。

BounceInterpolator:快到目标值时值会跳跃。

CycleIinterpolator:动画循环一定次数,值的改变为一正弦函数:Math.sin(2 * mCycles * Math.PI * input)。

LinearInterpolator:线性均匀改变。

OvershottInterpolator:最后超出目标值然后缓慢改变到目标值。

3.2.6 在 xml 中使用属性动画

我们可以像下面这样定义一个属性动画,

android:propertyName="string"

android:duration="int"

android:valueFrom="float | int | color"

android:valueTo="float | int | color"

android:startOffset="int"

android:repeatCount="int"

android:repeatMode=["repeat" | "reverse"]

android:valueType=["intType" | "floatType"]/>

android:duration="int"

android:valueFrom="float | int | color"

android:valueTo="float | int | color"

android:startOffset="int"

android:repeatCount="int"

android:repeatMode=["repeat" | "reverse"]

android:valueType=["intType" | "floatType"]/>

...

这里的android:ordering用于控制子动画启动方式是先后有序的还是同时进行,两个可选参数: sequentially 表示动画按照先后顺序;together(默认)表示动画同时启动。

这里的 标签的含义如下:

%E5%B1%9E%E6%80%A7%E5%8A%A8%E7%94%BBXML.png

这样在 XML 中定义了属性动画之后,我们可以在代码中通过工具类获取到动画实例并使用:

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext, R.animtor.property_animator);

set.setTarget(myObject);

set.start();

4、使用动画的注意事项

内存耗尽:使用帧动画的时候防止因为图片过多导致 OOM。

View 动画并没有真正改变 View 的位置:View 动画并没有真正改变 View 的属性,即 View 动画执行之后并未改变 View 的真实布局属性值。譬如我们在布局中有一个 Button 在屏幕上方,我们设置了平移动画移动到屏幕下方然后保持动画最后执行状态呆在屏幕下方,这时如果点击屏幕下方动画执行之后的 Button 是没有任何反应的,而点击原来屏幕上方没有 Button 的地方却响应的是点击 Button 的事件。

内存泄漏:使用属性动画的时候,当使用无限循环动画,需要在 Activity 退出的时候停止动画,不然可能会因为无法释放资源而导致 Activity 内存泄漏。

动画兼容:当 APP 需要兼容到 API 11 以下的时候就需要注意动画的兼容问题。

使用 dp 而不是 px:因为 px 在不同设备上面的兼容问题,使用动画的时候尽量使用 dp 作为单位。

硬件加速:使用硬件加速可以提升动画的流畅性。

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

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

相关文章

android 5.0 新功能,Android 5.0新特性有哪些?安卓5.0新功能汇总

Android 5.0新特性有哪些&#xff1f;经过一段时间曝光与测试后&#xff0c;期待已久的Android L系统正式发布了&#xff0c;新一代安卓系统正式名称为Android 5.0 Lollipop(棒棒糖)。Android 5.0新特性有哪些呢&#xff1f;下面&#xff0c;由百事网小编盘大家盘点一下安卓5.0…

cks子,间谍,局部Mo子和短管

本文是我们名为“ 用Mockito进行测试 ”的学院课程的一部分。 在本课程中&#xff0c;您将深入了解Mockito的魔力。 您将了解有关“模拟”&#xff0c;“间谍”和“部分模拟”的信息&#xff0c;以及它们相应的Stubbing行为。 您还将看到使用测试双打和对象匹配器进行验证的过…

8数据提供什么掩膜产品_工业轨式1-8路RS485数据(MODBUS RTU协议)厂家产品说明...

产品描述工业级数点对点光猫提供1-8路RS485&#xff08;MODBUS RTU协议&#xff09;&#xff1b;在光纤中传输&#xff0c;该产品突破了传统串行接口通讯距离与通讯速率的矛盾&#xff0c;同时&#xff0c;也解决了电磁干扰、地环干扰和雷电破坏的难题&#xff0c;大大提高了数…

BZOJ 4568 倍增维护线性基

在树的路径上选取一些点 使得这些点权xor后的结果最大 思路&#xff1a; 时限60s 59696ms卡过去了哈哈哈 //By SiriusRen #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N20005; ll T…

代码android点击效果,GitHub - likaiyuan559/TouchEffects: Android View点击特效TouchEffects,几行代码为所有控件添加点击效果...

Android 点击特效TouchEffectsTouchEffects能够帮助你更快速方便的增加点击时候的效果&#xff0c;TouchEffects的目标是打造一个稳定、全面、且能更方便的自定义及个性化的一款点击效果框架。功能特点&#xff1a;只需要几行代码便能为全局的View加上点击效果支持多种点击效果…

Linux下暴力破解工具Hydra详解

Linux下暴力破解工具Hydra详解 一、简介 Number one of the biggest security holes are passwords, as every password security study shows. Hydra is a parallized login cracker which supports numerous protocols to attack. New modules are easy to add, beside that,…

android的json解析方式,Android解析JSON方式

JSON数据格式的定义&#xff1a;JSON的全称是&#xff1a;JavaScript Object Notation&#xff0c;是一种轻量级的数据交换格式。它构建于两种结构&#xff1a;1、"名称/值" 对的集合(a collection of name / value pairs)。不同的语言中&#xff0c;它被理解为对象(…

uniapp无法使用substr_关公战秦琼------Excel、SPSS Modler和R的使用对比(下)

5. 数据可视化Excel在Excel中对数据可视化除常用的图表外&#xff0c;还有样式、迷你图等直接和实际数据来共同展示效果。另外&#xff0c;还可以与切片器、PowerView等功能结合来动态可视化。Excel中图表的类型很多&#xff0c;如常见的散点图、折线图、柱形图、饼图等&#x…

第三次预作业20155231邵煜楠:虚拟机上的Linux学习

java第三次预作业——虚拟机初体验(学习记录) 学习在笔记本上安装Linux操作系统通过老师给予的官网链接&#xff0c;下载了VirtualBox-5.1.14-112924-win和Ubuntu-16.04-desktop-amd64.iso开始按照安装&#xff0c;尽管如此&#xff0c;还是遇到来了一些问题。 -在选择虚拟机的…

miui11未升级android版本,MIUI 11稳定版正式推送,升级前你需要了解

原标题&#xff1a;MIUI 11稳定版正式推送&#xff0c;升级前你需要了解10月18日&#xff0c;MIUI官网正式宣布MIUI 11 正式推送&#xff0c;这是在小米MIX Alpha发布会之时同时推出的&#xff0c;在经过内测、公测后正式面向大众消费者推送。以下是一些您升级前需要了解的东西…

lumion自动保存_LUMION吊打MAX,轻松玩转规划渲染!

--文末获取&#xff1a;城市配景建筑模型包--大型场景渲染是LUMION渲染中难度最高的图纸首先&#xff0c;需要大量非常优质的配景包括&#xff1a;配景建筑、植物其次&#xff0c;对硬件要求也极高像这样的图纸渲染主体建筑周边需要布置大量的配景建筑没有个2080TI&#xff0c;…

在地图上 添加柱状_如何做出一份惊艳的PPT地图页?这2个字,你一定要知道!...

这篇文章&#xff0c;咱们就从一个读者私信给我的案例来说&#xff0c;就是这张PPT&#xff1a;他当时问我的问题是&#xff0c;怎么把这个表格优化的更美观&#xff1f;坦白讲&#xff0c;这是一个无解的问题&#xff0c;为什么这么说呢&#xff1f;咱们简单对这个图表分析&am…

akka与neety_Akka STM –与STM Ref和Agent一起打乒乓球

akka与neety乒乓是一个经典示例&#xff0c;其中2个玩家&#xff08;或线程&#xff09;访问共享资源–乒乓表并在彼此之间传递Ball&#xff08;状态变量&#xff09;。 使用任何共享资源&#xff0c;除非我们同步访问&#xff0c;否则线程可能会遇到潜在的死锁情况。 PingPong…

怎样调用另一个html中的元素,html – 使用DIV作为另一个元素的背景

这里我用2个div做了一个例子&#xff1a;> .content,包含前端所需的一切> .background – 包含文本,图像和背景中的所有其他内容要将一个div包装在另一个div上(制作叠加层),你必须将它们放入相同的元素中,在本例中它是#wrapper div.放置位置&#xff1a;包装的相对宽度/高…

在running android lint期间发生了内部错误.,Eclipse出现quot;Running Android Lint has encountered a problemquot...

近期打开Eclipse的时候&#xff0c;总是发生这种一个错误&#xff1a;"Running Android Lint has encountered a problem"。截图例如以下&#xff1a;。可是Eclipse能够正常执行程序。不会造成其它影响。可是每次打开Eclipse时。总是看到这个警告&#xff0c;心情会非…

idea 导出war包_使用IDEA实现远程代码DEBUG调试教程详解

我们在使用 IDEA DEBUG调试代码的时候&#xff0c;常常见到控制台会输出一句这样的话&#xff1a;「Connected to the target VM, address: 127.0.0.1:62981, transport: socket」&#xff0c;所以即使代码不在本地运行&#xff0c;只要JVM打开调试模式&#xff0c;并且网络能够…

鸿蒙os2.0发布回放,华为HarmonyOS 2.0系统发布会内容大全 鸿蒙os6月2日直播回放地址入口...

华为鸿蒙os6月2日直播回放在哪里看&#xff1f;华为HarmonyOS 2系统发布会说了些啥&#xff1f;HarmonyOS 2系统在6月2日正式发布了&#xff0c;之前预约过的小伙伴现在就可以更新体验了&#xff0c;这次发布将会对安卓系统一个重大的革新&#xff0c;将会彻底颠覆之前的安卓系…

python中当地时间_R 与 Python 中与时间相关内容的梳理

约万字长文预警&#xff0c;如果你没时间&#xff0c;就不用看了&#xff0c;这就是一个梳理的文章&#xff0c;方便我后来找资料。因为工作的关系&#xff0c;近期需要梳理一些 Python 的知识(可能有小伙伴知道了&#xff0c;LI-6800 搞了个大动作&#xff0c;支持 Python 编程…

JavaOne 2015:为JDK 9做准备– blog @ CodeFX

JavaOne 2015看到了Project Jigsaw团队关于Java 9中的模块化的一系列讨论 。它们都是非常有趣的&#xff0c;并且充满了宝贵的信息&#xff0c;我敦促每个Java开发人员都注意它们。 除此之外&#xff0c;我想给社区一种搜索和引用它们的方法&#xff0c;因此我在这里总结一下&…

华为oj----iNOC产品部-杨辉三角的变形 .

此题提供三种方法&#xff0c;第一种&#xff0c;一开始就能想到的&#xff0c;设置一个足够大的数组存储生成的杨辉三角&#xff0c;然后进行判断就行,此方法参见&#xff1a;华为oj iNOC产品部-杨辉三角的变形 另一种方法是采用递归&#xff1a; 三角形的每行的个数为2*n-1,n…