精华内容
下载资源
问答
  • 我们知道AnimationController.forward()可以正向播放动画AnimationController.reverse()可以反向播放动画,播完即停止。若想让动画播完还可以重新播放不断循环,可以调用 AnimationController.repeat():从头开始...
  • Animation动画详解 - v1.0

    2018-12-10 21:02:21
    • 2、《Animation动画详解(二)——Interpolator插值器》 • 3、《Animation动画详解(三)—— 代码生成alpha、scale、translate、rotate、set及插值器动画》 • 4、《Animation动画详解(四)——ValueAnimator...
  • android Animation动画实现loading效果

    热门讨论 2015-07-28 14:27:23
    android Animation动画实现loading效果
  • Animation动画实例

    2016-01-29 09:31:11
    Animation 动画实例,很有价值,值得参考。
  • wpf Animation动画效果演示,包含多个实例

    千次下载 热门讨论 2014-11-10 14:51:50
    利用WPF Animation 开发的动画,包含多个实例,附源码
  • Animation 动画详解

    2018-04-08 13:53:07
    Animation 动画详解 Animation 动画详解 Animation 动画详解Animation 动画详解Animation 动画详解Animation 动画详解
  • Animation动画的解析与自定义Animation动画
  • Animation动画概述和执行原理

    千次阅读 2018-12-27 16:49:02
    1 Animation动画简介 Developers:https://developer.android.google.cn/reference/android/view/animation/package-summary Android中动画非常常用,很多效果都需要动画的配合,android提供了多种动画类型,为...

    动画入门和进阶文章列表:

    Animation动画概述和执行原理
    Android动画之补间动画TweenAnimation
    Android动画之逐帧动画FrameAnimation
    Android动画之插值器简介和系统默认插值器
    Android动画之插值器Interpolator自定义
    Android动画之视图动画的缺点和属性动画的引入
    Android动画之ValueAnimator用法和自定义估值器
    Android动画之ObjectAnimator实现补间动画和ObjectAnimator自定义属性
    Android动画之ObjectAnimator中ofXX函数全解析-自定义Property,TypeConverter,TypeEvaluator
    Android动画之AnimatorSet联合动画用法
    Android动画之LayoutTransition布局动画
    Android动画之共享元素动画
    Android动画之ViewPropertyAnimator(专用于view的属性动画)
    Android动画之Activity切换动画overridePendingTransition实现和Theme Xml方式实现
    Android动画之ActivityOptionsCompat概述
    Android动画之场景变换Transition动画的使用
    Android动画之Transition和TransitionManager使用
    Android动画之圆形揭露动画Circular Reveal

    1 Animation动画简介

    Developers:https://developer.android.google.cn/reference/android/view/animation/package-summary

    Android中动画非常常用,很多效果都需要动画的配合,android提供了多种动画类型,为创建多彩的android程序提供了支持。提供的动画类型包括:补间动画,帧动画,属性动画,补间动画和帧动画被称为视图动画。

    对于Animation动画,android提供了两种机制来创建视图动画,
    一种是tweened animation(补间动画),
    一种是frame-by-frame animation(逐帧动画) 。
    Tweened animation 可以实现view一系列简单的转换(位置,尺寸,旋转,透明度),
    frame-by-frame 通过加载一系列drawable资源,实现动画。

    视图动画只能作用于View,且动画类型是固定的。

    补间动画:确定了view的开始的视图样式和结束的视图样式,动画过程中系统会补全变化中的状态,最终就实现了动画效果。

    补间动画的种类:

    • translate (平移动画)
    • scale (缩放动画)
    • rotate (旋转动画)
    • alpha (透明度动画)

    补间动画可以利用xml文件和动画类进行实现,对应的具体动画类:

    • translate(平移动画) 对应 TranslateAnimation
    • scale (缩放动画) 对应 ScaleAnimation
    • rotate (旋转动画) 对应 RotateAnimation类
    • alpha ( 透明度动画) 对应 AlphaAnimation 类

    补间动画一般利用xml文件实现,如果利用xml文件实现动画,需要在res/anim文件夹下穿件动画文件。

    2 Animation 基类

    Animation作为补间动画的基类,具有许多动画公共的属性和方法:
    在这里插入图片描述
    在android.view.animation包下,可以看出是作用于view的。
    直接子类有:AlphaAnimation,AnimationSet,RotateAnimation,ScaleAnimatioin,TranslateAnimation。
    XML属性包括:
    在这里插入图片描述
    下面会列举Animation中公共属性在xml文件中的表示和代码类中的设置方式及效果:
    每一项包括Animation中公共属性在xml文件中的表示和代码类中的设置方式及效果

    • android:detachWallpaper 对应setDetachWallpaper(boolean):是否在壁纸上运行,取值true,flase;
    • android:duration 对应setDuration(long):动画持续时间,参数单位为毫秒;
    • android:fillAfter 对应setFillAfter(boolean):动画结束时view是否保持动画最后的状态,默认值为false;
    • android:fillBefore 对应setFillBefore(boolean):动画结束时view是否还原到开始动画前的状态,和fillAfter行为是冲突的,所以只有当fillBefore为true或者fillEnabled不为true才生效。默认是true
    • android:fillEnabled 对应setFillEnabled(boolean):如果 fillEnabled 取值为true,animation将使用fillBefore的值,否则fillBefore将被忽略。都是在动画结束时还原到原来的状态。
    • android:interpolator 对应setInterpolator(Interpolator):设定插值器;
    • android:repeatCount对应setRepeatCount(int):动画重复次数,可以是具体次数,也可以是INFINITE(-1)一直循环。
    • android:repeatMode 对应setRepeatMode(int):重复类型有两个值,reverse表示倒序回放,restart表示从头播放,需要和repeateCount配合使用。
    • android:startOffset对应setStartOffset(long):调用start函数之后等待开始运行的时间,单位为毫秒;
    • android:zAdjustment 对应setZAdjustment(int)表示被设置动画的内容运行时在Z轴上的位置(top/bottom/normal),默认为normal,一般不需要设置。

    Animation构造函数:一般情况用不到
    Animation():duration默认0ms,default interpolator,fillBefore默认true,fillAfter默认false
    Animation(Context context, AttributeSet attrs):利用attributeset和context初始化

    3 动画开启的方法:start(),startNow()

    这两个方法有什么区别呢?

    /**
     * Convenience method to start the animation the first time
     * {@link #getTransformation(long, Transformation)} is invoked.
     */
    public void start() {
        setStartTime(-1);
    }
    
    /**
     * Convenience method to start the animation at the current time in
     * milliseconds.
     */
    public void startNow() {
        setStartTime(AnimationUtils.currentAnimationTimeMillis());
    }
    

    看两个函数的注释知道:
    start()函数当getTransformation()第一次被调用的时候开始执行。
    startNow()动画被立即执行
    start和startNow内部都是调用setStartTime函数,setStartTime函数是设置动画开始执行的时间。start函数设置setStartTime(-1)会等待getTransformation第一次执行时才开始执行动画,startNow是setStartTime(AnimationUtils.currentAnimationTimeMillis()设置了具体的开始时间,动画会立刻开始执行。
    所以start函数调用后不是立即执行动画,startNow是立即执行动画。

    4 动画真正实现的地方在哪里

    Animation是动画的基类,所以具体动画的操作一定在其子类中,通过分析可知道,最终实现动画操作在Animation类的applyTransformation()方法中,各个子类会实现这个方法,进行动画操作。

    /**
     * Helper for getTransformation. Subclasses should implement this to apply
     * their transforms given an interpolation value.  Implementations of this
     * method should always replace the specified Transformation or document
     * they are doing otherwise.
     *
     * @param interpolatedTime The value of the normalized time (0.0 to 1.0)
     *        after it has been run through the interpolation function.
     * @param t The Transformation object to fill in with the current
     *        transforms.
     */
    protected void applyTransformation(float interpolatedTime, Transformation t) {
    }
    

    从Animation类内部可知applyTransformation()函数会被getTransformation()函数调用。Transformation类包括matrix,scale,clip等变换信息。

    getTransformation()内部调用了applyTransformation(),来看看getTransformation内部的逻辑:

    getTransformation()

    getTransformation函数内部判断动画是否执行完毕,如果执行完毕返回false,如果动画还没有执行完返回true.

    public boolean getTransformation(long currentTime, Transformation outTransformation) {
    //如果mStartTime == -1,初始化动画开始时间
        if (mStartTime == -1) {
            mStartTime = currentTime;
        }
    
    //计算动画已经执行到的位置
        final long startOffset = getStartOffset();
        final long duration = mDuration;
        float normalizedTime;
        if (duration != 0) {
            normalizedTime = ((float) (currentTime - (mStartTime + startOffset))) /
                    (float) duration;
        } else {
                  normalizedTime = currentTime < mStartTime ? 0.0f : 1.0f;
        }
    
    //判断动画是否被取消或者时间超过1.0f,为true表示动画结束或者已经被取消
        final boolean expired = normalizedTime >= 1.0f || isCanceled();
    //设置动画是否完成标识
        mMore = !expired;
    //处理fillEnable
        if (!mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);
    //处理其他参数
        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);
        }
    
    //如果动画已经结束,判断重复执行操作
        if (expired) {
            if (mRepeatCount == mRepeated || isCanceled()) {
                if (!mEnded) {
                    mEnded = true;
                    guard.close();
                    fireAnimationEnd();
                }
            } else {
        if (mRepeatCount > 0) {
                    mRepeated++;
                }
    
                if (mRepeatMode == REVERSE) {
                    mCycleFlip = !mCycleFlip;
                }
    
                mStartTime = -1;
                mMore = true;
    
                fireAnimationRepeat();
            }
        }
    
    //动画还没有执行完
        if (!mMore && mOneMoreTime) {
            mOneMoreTime = false;
            return true;
        }
    
    //所以mMore表示动画是否执行完了,为true时表示还没有执行完
        return mMore;
    }
    
    

    getTransformation函数又是在哪里执行的呢?

    5 View 如何执行动画

    分析getTransformation在哪里执行我们需要先分析View如何执行动画。
    一般的步骤是定义好Animation对象设置属性之后,调用startAnimation()函数。
    View中startAnimation函数源码:

    /**
     * Start the specified animation now.
     *
     * @param animation the animation to start now
     */
    public void startAnimation(Animation animation) {
        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
        setAnimation(animation);
        invalidateParentCaches();
        invalidate(true);
    }
    

    首先设置了START_ON_FIRST_FRAME表示,它的值为-1,相当于调用了Animation的start()函数,然后调用了setAnimation设置了animation方法,之后调用了invalidateParentCaches和invalidate函数。startAnimation这个函数的作用是立即开始执行动画,所以我们就知道了执行动画需要设置以上四个参数。

    再看View 的setAnimation的方法:

    /**
     * Sets the next animation to play for this view.
     * If you want the animation to play immediately, use
     * {@link #startAnimation(android.view.animation.Animation)} instead.
     * This method provides allows fine-grained
     * control over the start time and invalidation, but you
     * must make sure that 1) the animation has a start time set, and
     * 2) the view's parent (which controls animations on its children)
     * will be invalidated when the animation is supposed to
     * start.
     *
     * @param animation The next animation, or null.
     */
    public void setAnimation(Animation animation) {
        mCurrentAnimation = animation;
    
        if (animation != null) {
                  if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
            }
            animation.reset();
        }
    }
    

    setAnimation 把animation对象设置给了mCurrentAnimation,然后设置了animation的startTime,最后调用了animation的reset函数。
    仔细阅读注释:调用了setAnimation 方法后,如果想让动画执行需要两个条件,第一个是有个开始执行的时间,另外一个是view的父类调用了invalidated方法,这样动画才会执行。
    所以还得继续观察invalidateParentCaches函数,内部只是设置了表示,再看invalidate(true)方法。

    /**
     * This is where the invalidate() work actually happens. A full invalidate()
     * causes the drawing cache to be invalidated, but this function can be
     * called with invalidateCache set to false to skip that invalidation step
     * for cases that do not need it (for example, a component that remains at
     * the same dimensions with the same content).
     *
     * @param invalidateCache Whether the drawing cache for this view should be
     *            invalidated as well. This is usually true for a full
     *            invalidate, but may be set to false if the View's contents or
     *            dimensions have not changed.
     * @hide
     */
    public void invalidate(boolean invalidateCache) {
        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
    }
    

    invalidate() 内部其实是调用了 ViewGroup 的 invalidateChild(),内部会一直向上会执行 ViewRootImpl 的 invalidateChildInParent() ,最终触发的是ViewRootImpl 的 performTraversals(),进而执行view的测量,布局,绘制工作。(具体流程会在后续分析view绘制流程时讲解)。

    所以需要执行动画时,最终会触发一次view树形结构的遍历绘制工作,动画的执行应该在view的绘制过程中进行。

    看View类顶部关于Animation的注释:

    * You can attach an {@link Animation} object to a view using
    * {@link #setAnimation(Animation)} or
    * {@link #startAnimation(Animation)}. The animation can alter the scale,
    * rotation, translation and alpha of a view over time. If the animation is
    * attached to a view that has children, the animation will affect the entire
    * subtree rooted by that node. When an animation is started, the framework will
    * take care of redrawing the appropriate views until the animation completes.
    * </p>
    

    最后一句当animation 开始运行后,framework 将关注重新绘制view视图知道动画结束,所以动画跟随view的绘制一起执行。对应上面的结论,动画开始时会触发view树的重新绘制。

    View绘制过程中会调用view的draw方法,draw方法内部会调用applyLegacyAnimation。

    //**
     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
     * case of an active Animation being run on the view.
     */
    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
            Animation a, boolean scalingRequired) {
        Transformation invalidationTransform;
        final int flags = parent.mGroupFlags;
        final boolean initialized = a.isInitialized();
    //动画还没有初始化,就初始化动画并告诉子view,当前view添加了动画
    if (!initialized) {
            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
            onAnimationStart();
        }
    
        final Transformation t = parent.getChildTransformation();
    //获取动画是否执行完
        boolean more = a.getTransformation(drawingTime, t, 1f);
        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
            if (parent.mInvalidationTransformation == null) {
                parent.mInvalidationTransformation = new Transformation();
            }
            invalidationTransform = parent.mInvalidationTransformation;
            a.getTransformation(drawingTime, invalidationTransform, 1f);
        } else {
            invalidationTransform = t;
        }
    
    //如果动画没有结束,循环调用,会触发view树的遍历绘制
        if (more) {
            if (!a.willChangeBounds()) {
                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
                                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
                    parent.invalidate(mLeft, mTop, mRight, mBottom);
                }
            } else {
                if (parent.mInvalidateRegion == null) {
                    parent.mInvalidateRegion = new RectF();
                }
                final RectF region = parent.mInvalidateRegion;
                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
                        invalidationTransform);
    
                         parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
    
                final int left = mLeft + (int) region.left;
                final int top = mTop + (int) region.top;
                parent.invalidate(left, top, left + (int) (region.width() + .5f),
                        top + (int) (region.height() + .5f));
            }
        }
        return more;
    }
    

    applyLegacyAnimation这个函数内部调用了getTransformation函数,最终动画得到执行,getTransformation函数会返回动画是否完成的状态,完成为false,没完成为true,如果没有完成会再次遍历view树进行绘制。

    所以viewgroup下的任何一个view执行动画,那么都会导致view执行整个绘制流程,最终会调用viewGroup的dispatchDraw()然后内部又调用drawChild去绘制各个子View,子view内部调用draw方法绘制自身。

    view 动画怎么绘制的呢?

    既然知道了动画是在view的draw函数中绘制的,我们看一下view的draw函数。
    draw三个参数的方法:
    可以看到内部获取了Animation和getChildTransformation,然后对画布进行了变换,就实现了对view的动画操作。

     /**
         * This method is called by ViewGroup.drawChild() to have each child view draw itself
         */
        boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
            boolean more = false;
            Transformation transformToApply = null;
            boolean concatMatrix = false;
            final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
            //获取动画
            final Animation a = getAnimation();
            if (a != null) {
            //有动画,通知执行
                more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
                concatMatrix = a.willChangeTransformationMatrix();
                if (concatMatrix) {
                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
                }
                //获取Transformtion信息
                transformToApply = parent.getChildTransformation();
            } else {
                。。。。。。
            }
            。。。。。。。
            int restoreTo = -1;
            //执行动画之前保存画布
            if (!drawingWithRenderNode || transformToApply != null) {
                restoreTo = canvas.save();
            }
            //对画布进行操作
            if (offsetForScroll) {
                canvas.translate(mLeft - sx, mTop - sy);
            } else {
                if (!drawingWithRenderNode) {
                    canvas.translate(mLeft, mTop);
                }
                if (scalingRequired) {
                    if (drawingWithRenderNode) {
                        // TODO: Might not need this if we put everything inside the DL
                        restoreTo = canvas.save();
                    }
                    // mAttachInfo cannot be null, otherwise scalingRequired == false
                    final float scale = 1.0f / mAttachInfo.mApplicationScale;
                    canvas.scale(scale, scale);
                }
            }
    
            float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
            if (transformToApply != null
                    || alpha < 1
                    || !hasIdentityMatrix()
                    || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
                if (transformToApply != null || !childHasIdentityMatrix) {
                    int transX = 0;
                    int transY = 0;
    
                    if (offsetForScroll) {
                        transX = -sx;
                        transY = -sy;
                    }
    
                    if (transformToApply != null) {
                        if (concatMatrix) {
                            if (drawingWithRenderNode) {
                                renderNode.setAnimationMatrix(transformToApply.getMatrix());
                            } else {
                                // Undo the scroll translation, apply the transformation matrix,
                                // then redo the scroll translate to get the correct result.
                                canvas.translate(-transX, -transY);
                                canvas.concat(transformToApply.getMatrix());
                                canvas.translate(transX, transY);
                            }
                            parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
                        }
    
                        float transformAlpha = transformToApply.getAlpha();
                        if (transformAlpha < 1) {
                            alpha *= transformAlpha;
                            parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
                        }
                    }
    
                    if (!childHasIdentityMatrix && !drawingWithRenderNode) {
                        canvas.translate(-transX, -transY);
                        canvas.concat(getMatrix());
                        canvas.translate(transX, transY);
                    }
                }
    
                // Deal with alpha if it is or used to be <1
                if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
                    if (alpha < 1) {
                        mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
                    } else {
                        mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
                    }
                    parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
                    if (!drawingWithDrawingCache) {
                        final int multipliedAlpha = (int) (255 * alpha);
                        if (!onSetAlpha(multipliedAlpha)) {
                            if (drawingWithRenderNode) {
                                renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
                            } else if (layerType == LAYER_TYPE_NONE) {
                                canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
                                        multipliedAlpha);
                            }
                        } else {
                            // Alpha is handled by the child directly, clobber the layer's alpha
                            mPrivateFlags |= PFLAG_ALPHA_SET;
                        }
                    }
                }
            } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
                onSetAlpha(255);
                mPrivateFlags &= ~PFLAG_ALPHA_SET;
            }
          。。。。。。。
    
    		//恢复画布
            if (restoreTo >= 0) {
                canvas.restoreToCount(restoreTo);
            }
            if (more && hardwareAcceleratedCanvas) {
                if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
                    // alpha animations should cause the child to recreate its display list
                    //还有动画继续通知
                    invalidate(true);
                }
            }
    
            mRecreateDisplayList = false;
    
            return more;
        }
    

    绘制子view都会先对画布状态进行保存save(),绘制完后,又会恢复restore(),所以一个view的绘制不会影响另外一个子view的绘制,但如果该view是viewgroup,会影响到其所有的子view的绘制,所以动画发生时不是类似调用invalidate,只绘制view自身,而是由上而下,重绘ViewGroup导致了绘制子View,子view绘制,只是变换了自己所在的画布的坐标系,其实属性没有改变。
    Android动画就是通过父view来不断调整子view的画布canvas坐标系来实现的,发生动画的其实是父View而不是该view。所以 补间动画其实只是调整了子view画布canvas的坐标系,其实并没有修改任何属性,所以只能在原位置才能处理触摸事件。

    以上我们反向推导了动画执行的过程,下面总结一下:
    当view调用了 View.startAnimation() 时动画并没有马上就执行,会触发遍历view树的绘制,
    调用到 View 的 draw() 方法,如果 View 有绑定动画,那么会去调用applyLegacyAnimation(),内部调用 getTransformation() 来根据当前时间计算动画进度,紧接着调用 applyTransformation() 并传入动画进度来应用动画。getTransformation() 会返回动画是否执行完成的状态, applyLegacyAnimation() 会根据 getTransformation() 的返回值来决定是否通知 ViewRootImpl 再发起一次遍历请求,遍历 View 树绘制,重复上面的步骤,直到动画结束。

    补间动画的绘制实际上是父布局不停地改变自己的Canvas坐标,而子view虽然位置没有变化,但是画布所在Canvas的坐标发生了变化视觉效果也就发生了变化,其实并没有修改任何属性,所以只能在原位置才能处理触摸事件。

    展开全文
  • animation动画全解

    千次阅读 2020-07-23 16:54:58
    animation八大属性共用 代码 HTML <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /&...

    animation八大属性共用

    代码

    HTML

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>Static Template</title>
        <link rel="stylesheet" href="./index.css" />
      </head>
      <body>
        <div class="box"></div>
        <div class="box"></div>
        <div class="box"></div>
        <div class="box"></div>
      </body>
    </html>
    
    

    CSS

    .box {
      width: 100px;
      height: 100px;
      background-color: red;
      border-radius: 50%;
      margin-bottom: 20px;
    }
    .box:nth-child(2n + 1) {
      animation: move 2s linear infinite alternate;
    }
    .box:nth-child(2n) {
      animation: move 2s linear infinite alternate-reverse forwards 1s;
    }
    
    .box:hover {
      animation-play-state: paused;
    }
    
    @keyframes move {
      0% {
        transform: translate(0, 0);
      }
      100% {
        transform: translate(400px, 0);
      }
    }
    
    

    效果

    在这里插入图片描述

    控制台查看八大属性的全称和值

    在这里插入图片描述

    八大属性的意义与取值

    animation-delay

    作用:

    定义动画于何时开始,即从动画应用在元素上到动画开始的这段时间的长度。

    默认值:

    0s,代表动画在应用到元素上后立即开始执行

    取值:

    正负值皆可。定义一个负值会让动画立即开始。但是动画会从它的动画序列中某位置开始。例如,如果设定值为-1s,动画会从它的动画序列的第1秒位置处立即开始。

    animation-direction

    作用:

    指示动画是否反向播放

    默认值:

    normal,每个循环内动画向前循环,就是说每个动画循环结束,动画重置到起点重新开始

    取值

    alternate

    动画交替反向运行。带时间功能的函数也反向,比如,ease-in 在反向时成为ease-out。计数取决于开始时是奇数迭代还是偶数迭代。小球的循环运动通常使用该值。

    reverse

    反向运行动画,每周期结束后,从动画结束的尾部到头反向运行。

    alternate-reverse

    反向交替运行动画。即动画第一次运行时是反向的,然后下一次是正向,后面依次循环。决定奇数次或偶数次的计数从1开始。

    animation-duration

    作用:

    指定一个动画周期的时长。

    默认值:

    默认值为0s,表示无动画,直接到最后的状态

    取值:

    time,表达一个动画周期的时长,单位为秒(s)或者毫秒(ms),无单位值则无效。

    animation-fill-mode

    作用:

    设置CSS动画在执行之前和之后如何将样式应用于其目标。

    默认值:

    none

    当动画未执行时,动画将不会将任何样式应用于目标

    取值(具体请看mdn):

    mdn对此属性取值的解释
    forwards

    动画完成后,元素状态保持为最后一帧的状态。

    backwards

    动画将在应用于目标时立即应用第一个关键帧中定义的值,并在animation-delay期间保留此值。 第一个关键帧取决于animation-direction的值

    both

    动画将遵循forwards和backwards的规则,从而在两个方向上扩展动画属性

    animation-iteration-count

    作用:

    定义动画在结束前运行的次数,可以是1次,也可以无限循环。如果指定了多个值,每次播放动画时,将使用列表中的下一个值,在使用最后一个值后循环回第一个值。

    默认值:

    默认值为1,表示只运行一次

    取值:

    infinite

    无限循环播放动画.

    <number>

    动画播放的次数。可以用小数定义循环,来播放动画周期的一部分:例如,0.5 将播放到动画周期的一半。但不可设为负值。

    animation-name

    作用

    属性指定应用的一系列动画,每个名称代表一个由@keyframes定义的动画序列

    默认值

    无默认值

    取值

    @keyframes定义的动画序列名

    animation-play-state

    作用:

    定义一个动画是否运行或者暂停。可以通过查询它来确定动画是否正在运行。另外,它的值可以被设置为暂停和恢复的动画的重放。

    注意:

    恢复一个已暂停的动画,将从它开始暂停的时候,而不是从动画序列的起点开始在动画。

    默认值:

    无默认值

    取值

    running

    当前动画正在运行。

    paused

    当前动画已被停止。

    animation-timing-function

    作用:

    定义CSS动画在每一动画周期中执行的节奏。

    默认值

    ease

    取值

    可能值为一或多个 <timing-function>。比如ease-in、ease-out、ease-in-out、linear、step-start、step-end、cubic-bezier(0,.7,.57,.81)

    调试贝塞尔曲线

    代码

    HTML

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>Static Template</title>
        <link rel="stylesheet" href="./index.css" />
      </head>
      <body>
        <div id="box"></div>
      </body>
    </html>
    
    

    CSS

    #box {
      width: 100px;
      height: 100px;
      background-color: red;
      border-radius: 50%;
      animation: move 2s linear infinite alternate;
    }
    
    @keyframes move {
      0% {
        transform: translate(0, 0);
      }
      100% {
        transform: translate(300px, 0);
      }
    }
    
    

    调试

    示例

    在这里插入图片描述

    位置

    在这里插入图片描述

    看每帧动画

    代码

    HTML

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>Static Template</title>
        <link rel="stylesheet" href="./index.css" />
      </head>
      <body>
        <div id="box"></div>
      </body>
    </html>
    
    

    CSS

    #box {
      width: 100px;
      height: 100px;
      background-color: red;
      border-radius: 50%;
      animation: move 2s steps(50) infinite alternate;
    }
    
    @keyframes move {
      0% {
        transform: translate(0, 0);
      }
      100% {
        transform: translate(300px, 0);
        border-radius: 0;
      }
    }
    
    

    效果

    在这里插入图片描述

    微调

    如果将steps()的参数改为5

    效果

    看上去非常的“卡顿”
    在这里插入图片描述

    实现一个进度条特效

    代码

    HTML

    linear-gradient函数的详细介绍

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>Static Template</title>
        <link rel="stylesheet" href="./index.css" />
      </head>
      <body>
        <div id="box"></div>
      </body>
    </html>
    
    

    CSS

    #box {
      height: 20px;
      background: linear-gradient(#f0f, #f0f);
      background-repeat: no-repeat;
      border: 1px solid red;
      background-size: 0;
      animation: move 2s linear backwards infinite;
    }
    
    #box:hover {
      animation-play-state: paused;
    }
    
    @keyframes move {
      100% {
        background-size: 100%;
      }
    }
    
    

    效果

    在这里插入图片描述

    小球的移动(面试题)

    初级版本

    缺点

    小球运动结束不能沿着原路径动画返回

    HTML

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>Static Template</title>
        <link rel="stylesheet" href="./index.css" />
      </head>
      <body>
        <div id="box"></div>
      </body>
    </html>
    
    

    CSS

    #box {
      width: 50px;
      height: 50px;
      background-color: red;
      border-radius: 50%;
      animation: move 2s linear;
    }
    
    @keyframes move {
      0% {
        transform: translate(0, 0);
      }
      100% {
        transform: translate(200px, 0);
      }
    }
    
    

    效果

    在这里插入图片描述

    优化一版

    缺点

    按照定义的运动时长运动结束以后还是突兀的从头开始

    HTML

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>Static Template</title>
        <link rel="stylesheet" href="./index.css" />
      </head>
      <body>
        <div id="box"></div>
      </body>
    </html>
    
    

    CSS

    #box {
      width: 50px;
      height: 50px;
      background-color: red;
      border-radius: 50%;
      animation: move 4s linear infinite;
    }
    
    @keyframes move {
      0%,
      66% {
        transform: translate(0, 0);
      }
      33%,
      100% {
        transform: translate(200px, 0);
      }
    }
    
    

    效果

    在这里插入图片描述

    优化二版

    优点

    丝滑

    HTML

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>Static Template</title>
        <link rel="stylesheet" href="./index.css" />
      </head>
      <body>
        <div id="box"></div>
      </body>
    </html>
    
    

    CSS

    #box {
      width: 50px;
      height: 50px;
      background-color: red;
      border-radius: 50%;
      animation: move 2s linear infinite alternate;
    }
    
    @keyframes move {
      0% {
        transform: translate(0, 0);
      }
      100% {
        transform: translate(200px, 0);
      }
    }
    
    
    

    效果

    在这里插入图片描述

    参考

    https://developer.mozilla.org/zh-CN/docs/Web/CSS/animation
    https://juejin.im/post/5cdd178ee51d456e811d279b

    展开全文
  • animation动画--跳动

    千次阅读 2018-12-07 12:19:26
    第一个文字动画 &lt;title&gt;&lt;/title&gt; &lt;style&gt; .box{ width: 600px; height: 150px; margin: auto; margin-top: 300px; background-color: ...

    给大家分享一个小案例,让静态的一行字与一个球变为动态跳动
    第一个文字动画

    <title></title>
    		<style>
    			.box{
    				width: 600px;
    				height: 150px;
    				margin: auto;
    				margin-top: 300px;
    				background-color: deepskyblue;
    			}
    			.box p{
    				display: inline-block;
    				font-size: 50px;
    				text-align: center;
    				margin-left: 20px;
    				animation: dong 2s infinite; /*设置动画效果,dong与后面的动画设置相连接 完整运动时间为两秒,一直循环*/
    			}
    			/*选择第二个p标签*/
    			.box p:nth-of-type(2){
    				animation-delay: 0.5s;
    			}
    			.box p:nth-of-type(3){
    				animation-delay: 0.75s;
    			}
    			.box p:nth-of-type(4){
    				animation-delay: 1s;
    			}.box p:nth-of-type(5){
    				animation-delay: 1.25s;
    			}
    			.box p:nth-of-type(6){
    				animation-delay: 1.5s;
    			}
    			.box p:nth-of-type(7){
    				animation-delay: 1.75s;
    			}
    			.box p:nth-of-type(8){
    				animation-delay: 2s;
    			}
    			/*动画设置*/
    			@keyframes dong{
    				0%{}
    				50%{transform: translateY(-50px)}
    				100%{}
    			}
    		</style>
    	</head>
    	<body>
    		<div>
    			<div class="box">
    				<p>正</p>
    				<p>在</p>
    				<p>加</p>
    				<p>载</p>
    				<p>中</p>
    				<p>.</p>
    				<p>.</p>
    				<p>.</p>
    			</div>
    		</div>
    	</body>
    

    在这里插入图片描述
    在这里插入图片描述
    第二个小球跳动动画

    <title></title>
    		<style>
    			.div{
    				margin: 0 auto;
    				width: 800px;
    				height: 700px;
    				margin-top: 100px;
    			}
    			.box1{
    				width: 80px;
    				height: 80px;
    				border-radius: 50%;
    				background-image: linear-gradient(blue,black);/*给小球添加一个颜色渐变*/
    				margin-top: 500px;
    				margin-left: 400px;
    				animation:dong 2s infinite;
    			}
    			.box2{
    				width: 80px;
    				height: 10px;
    				border-radius: 50%;
    				background-color: cadetblue;
    				margin-left: 400px;
    			}
    			@keyframes dong{
    				0%{} 
    				50%{ transform: translateY(-300px);}
    				100%{}
    			}
    		</style>
    	</head>
    	<body>
    		<div class="div">
    			<div class="box1"></div>
    			<div class="box2"></div>
    		</div>	
    	</body>
    

    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • Animation动画

    万次阅读 2015-11-12 01:22:00
    1.Animation 动画类型 Android的animation由四种类型组成: XML中 alph 渐变透明度动画效果 scale 渐变尺寸伸缩动画效果 translate 画面转换位置移动动画效果 rotate 画面转移旋转动画效果 Java...

    首先介绍一下Animation:

    1.Animation 动画类型

    Android的animation由四种类型组成:

    XML中

    alph渐变透明度动画效果
    scale渐变尺寸伸缩动画效果
    translate画面转换位置移动动画效果
    rotate画面转移旋转动画效果

     

     

     

     

     

    JavaCode中

    AlphaAnimation渐变透明度动画效果
    ScaleAnimation渐变尺寸伸缩动画效果
    TranslateAnimation画面转换位置移动动画效果
    RotateAnimation画面转移旋转动画效果

     

     

     

     

     2.Android动画模式

    Animation主要有两种动画模式:

    一种是tweened animation(渐变动画)

    XML中JavaCode
    alphaAlphaAnimation
    scaleScaleAnimation

     

     

     

    一种是frame by frame(画面转换动画)

    XML中JavaCode
    translateTranslateAnimation
    rotateRotateAnimation

     

     

     

    下面我们将用Java代码来实现这些动画,并且,可以通过手动输入参数去改变动画;

    先看效果图:

     

     

    由于之前动图传到的是360云盘。。。所以现在动图看不了了。。。。

    我将四种动画写在了一个工具类中(注释的很详细了)

    AnimationTools.java:

    package com.soft.util;
    
    import android.view.animation.AlphaAnimation;
    import android.view.animation.Animation;
    import android.view.animation.AnimationSet;
    import android.view.animation.RotateAnimation;
    import android.view.animation.ScaleAnimation;
    import android.view.animation.TranslateAnimation;
    
    /**
     * @author zml2015
     * @date 2015-11-11 下午9:39:33
     * @version 1.0
     */
    public class AnimationTools {
    
    	/**
    	 * @param fromAlpha
    	 *            开始的透明度
    	 * @param toAlpha
    	 *            到大的透明度
    	 * @param durationMillis
    	 *            动画持续时间
    	 * @return
    	 */
    	public static AnimationSet alphaAnimation(float fromAlpha, float toAlpha,
    			long durationMillis) {
    		// true表示使用Animation的interpolator,false则是使用自己的
    		AnimationSet set = new AnimationSet(true);
    
    		Animation alpha = new AlphaAnimation(fromAlpha, toAlpha);
    
    		alpha.setDuration(durationMillis);
    		set.addAnimation(alpha);
    		return set;
    
    	}
    
    	/**
    	 * @param fromDegrees
    	 *            :从哪个旋转角度开始
    	 * @param toDegrees
    	 *            :转到什么角度
    	 * @param pivotXValue
    	 *            : x轴的值,0.5f表明是以自身这个控件的一半长度为x轴
    	 * @param pivotYValue
    	 *            :y轴的值,0.5f表明是以自身这个控件的一半长度为y轴
    	 * @param durationMillis
    	 *            动画持续时间
    	 * @return AnimationSet
    	 */
    	public static AnimationSet rotateAnimation(float fromDegrees,
    			float toDegrees, float pivotXValue, float pivotYValue,
    			long durationMillis) {
    		AnimationSet set = new AnimationSet(true);
    
    		// Animation.RELATIVE_TO_SELF==1;
    		// Animation.RELATIVE_TO_PARENTS==2;
    		// 后4个参数用于设置围绕着旋转的圆的圆心在哪里
    		Animation rotate = new RotateAnimation(fromDegrees, toDegrees, 1,
    				pivotXValue, 1, pivotYValue);
    		rotate.setDuration(durationMillis);
    		set.addAnimation(rotate);
    		return set;
    	}
    
    	/**
    	 * @param fromX
    	 *            x轴的初始值
    	 * @param toX
    	 *            x轴收缩后的值
    	 * @param fromY
    	 *            y轴的初始值
    	 * @param toY
    	 *            y轴收缩后的值
    	 * @param pivotXValue
    	 *            x轴的值,0.5f表明是以自身这个控件的一半长度为x轴
    	 * @param pivotYValue
    	 *            y轴的值,0.5f表明是以自身这个控件的一半长度为y轴
    	 * @param durationMillis
    	 *            动画持续时间
    	 * @return AnimationSet
    	 */
    	public static AnimationSet scaleAnimation(float fromX, float toX,
    			float fromY, float toY, float pivotXValue, float pivotYValue,
    			long durationMillis) {
    		AnimationSet set = new AnimationSet(true);
    
    		// Animation.RELATIVE_TO_SELF==1;
    		// Animation.RELATIVE_TO_PARENTS==2;
    		Animation sacle = new ScaleAnimation(fromX, toX, fromY, toY, 1,
    				pivotXValue, 1, pivotYValue);
    		sacle.setDuration(durationMillis);
    		set.addAnimation(sacle);
    		return set;
    	}
    
    	/**
    	 * @param fromXValue
    	 *            x轴的开始位置
    	 * @param toXValue
    	 *            x轴的结束位置
    	 * @param fromYValue
    	 *            y轴的开始位置
    	 * 
    	 * @param toYValue
    	 *            y轴的结束位置
    	 * @param durationMillis
    	 *            动画持续时间
    	 * @return AnimationSet
    	 */
    	public static AnimationSet translateAnimation(float fromXValue,
    			float toXValue, float fromYValue, float toYValue,
    			long durationMillis) {
    		AnimationSet set = new AnimationSet(true);
    
    		// Animation.RELATIVE_TO_SELF==1;
    		// Animation.RELATIVE_TO_PARENTS==2;
    		Animation translate = new TranslateAnimation(1, fromXValue, 1,
    				toXValue, 1, fromYValue, 1, toYValue);
    		translate.setDuration(durationMillis);
    		set.addAnimation(translate);
    		return set;
    	}
    }
    


    布局文件main.xml

    <span style="font-size:18px;"><ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            tools:context="com.zml.animation.MainActivity" >
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content" >
    
                <EditText
                    android:id="@+id/editText1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10"
                    android:hint="持续时间(ms)"
                    android:numeric="decimal" />
    
                <EditText
                    android:id="@+id/editText2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10"
                    android:hint="开始状态(0~1)"
                    android:numeric="decimal" />
    
                <EditText
                    android:id="@+id/editText3"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10"
                    android:hint="终止状态(0~1)"
                    android:numeric="decimal" >
    
                    <requestFocus />
                </EditText>
            </LinearLayout>
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content" >
    
                <EditText
                    android:id="@+id/et_rotate1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10"
                    android:hint="旋转角度开始"
                    android:numeric="decimal" />
    
                <EditText
                    android:id="@+id/et_rotate2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10"
                    android:hint="旋转角度结束"
                    android:numeric="decimal" />
    
                <EditText
                    android:id="@+id/et_rotate3"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10"
                    android:hint="x轴的值"
                    android:numeric="decimal" />
    
                <EditText
                    android:id="@+id/et_rotate4"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10"
                    android:hint="y轴的值"
                    android:numeric="decimal" />
    
                <EditText
                    android:id="@+id/et_rotate5"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10"
                    android:hint="持续时间"
                    android:numeric="decimal" />
            </LinearLayout>
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content" >
    
                <EditText
                    android:id="@+id/et_scale1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10"
                    android:hint="X轴初值"
                    android:numeric="decimal" />
    
                <EditText
                    android:id="@+id/et_scale2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10"
                    android:hint="X收缩后的值"
                    android:numeric="decimal" />
    
                <EditText
                    android:id="@+id/et_scale3"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10"
                    android:hint="Y轴初值"
                    android:numeric="decimal" />
    
                <EditText
                    android:id="@+id/et_scale4"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10"
                    android:hint="Y收缩后的值"
                    android:numeric="decimal" />
    
                <EditText
                    android:id="@+id/et_scale5"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10"
                    android:hint="x轴位置"
                    android:numeric="decimal" />
    
                <EditText
                    android:id="@+id/et_scale6"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10"
                    android:hint="y轴位置"
                    android:numeric="decimal" />
    
                <EditText
                    android:id="@+id/et_scale7"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10"
                    android:hint="时间"
                    android:numeric="decimal" />
            </LinearLayout>
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content" >
    
                <EditText
                    android:id="@+id/et_trans1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10"
                    android:hint="X轴初值"
                    android:numeric="decimal" />
    
                <EditText
                    android:id="@+id/et_trans2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10"
                    android:hint="X移动后的值"
                    android:numeric="decimal" />
    
                <EditText
                    android:id="@+id/et_trans3"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10"
                    android:hint="Y轴初值"
                    android:numeric="decimal" />
    
                <EditText
                    android:id="@+id/et_trans4"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10"
                    android:hint="Y移动后的值"
                    android:numeric="decimal" />
    
                <EditText
                    android:id="@+id/et_trans5"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10"
                    android:hint="时间"
                    android:numeric="decimal" />
            </LinearLayout>
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content" >
    
                <Button
                    android:id="@+id/alphaButton"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="淡入淡出" />
    
                <Button
                    android:id="@+id/rotateButton"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="旋转" />
    
                <Button
                    android:id="@+id/scaleButton"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="缩放" />
    
                <Button
                    android:id="@+id/translateButton"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="移动" />
            </LinearLayout>
    
            <ImageView
                android:id="@+id/imageView1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/dog" />
        </LinearLayout>
    
    </ScrollView></span>


    主页面管理文件(注释虽然比较少,但是写的还是比较简单明了的)

    MainActivity.java

     

    package com.zml.animation;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.ImageView;
    import android.widget.Toast;
    
    import com.soft.util.AnimationTools;
    
    public class MainActivity extends Activity implements OnClickListener {
    	private Button alphaButton = null;
    	private Button rotateButton = null;
    	private Button scaleButton = null;
    
    	private Button translateButton = null;
    	private EditText et_alpha1, et_alpha2, et_alpha3, et_rotate1, et_rotate2,
    			et_rotate3, et_rotate4, et_rotate5, et_scale1, et_scale2,
    			et_scale3, et_scale4, et_scale5, et_scale6, et_scale7, et_trans1,
    			et_trans2, et_trans3, et_trans4, et_trans5;
    	private ImageView iv_show;
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		alphaButton = (Button) findViewById(R.id.alphaButton);
    		rotateButton = (Button) findViewById(R.id.rotateButton);
    		scaleButton = (Button) findViewById(R.id.scaleButton);
    		translateButton = (Button) findViewById(R.id.translateButton);
    		alphaButton.setOnClickListener(this);
    		rotateButton.setOnClickListener(this);
    		scaleButton.setOnClickListener(this);
    		translateButton.setOnClickListener(this);
    
    		et_alpha1 = (EditText) findViewById(R.id.editText1);
    		et_alpha2 = (EditText) findViewById(R.id.editText2);
    		et_alpha3 = (EditText) findViewById(R.id.editText3);
    
    		et_rotate1 = (EditText) findViewById(R.id.et_rotate1);
    		et_rotate2 = (EditText) findViewById(R.id.et_rotate2);
    		et_rotate3 = (EditText) findViewById(R.id.et_rotate3);
    		et_rotate4 = (EditText) findViewById(R.id.et_rotate4);
    		et_rotate5 = (EditText) findViewById(R.id.et_rotate5);
    
    		et_scale1 = (EditText) findViewById(R.id.et_scale1);
    		et_scale2 = (EditText) findViewById(R.id.et_scale2);
    		et_scale3 = (EditText) findViewById(R.id.et_scale3);
    		et_scale4 = (EditText) findViewById(R.id.et_scale4);
    		et_scale5 = (EditText) findViewById(R.id.et_scale5);
    		et_scale6 = (EditText) findViewById(R.id.et_scale6);
    		et_scale7 = (EditText) findViewById(R.id.et_scale7);
    
    		et_trans1 = (EditText) findViewById(R.id.et_trans1);
    		et_trans2 = (EditText) findViewById(R.id.et_trans2);
    		et_trans3 = (EditText) findViewById(R.id.et_trans3);
    		et_trans4 = (EditText) findViewById(R.id.et_trans4);
    		et_trans5 = (EditText) findViewById(R.id.et_trans5);
    
    		iv_show = (ImageView) findViewById(R.id.imageView1);
    
    	}
    
    	@Override
    	public void onClick(View arg0) {
    		switch (arg0.getId()) {
    		case R.id.alphaButton:
    			if (et_alpha1.getText().toString().isEmpty()
    					|| et_alpha2.getText().toString().isEmpty()
    					|| et_alpha3.getText().toString().isEmpty())
    				Toast.makeText(MainActivity.this, "淡入淡出内容未填完整", 0).show();
    			else {
    				float fromAlpha = Float.parseFloat(et_alpha2.getText()
    						.toString());
    				float toAlpha = Float
    						.parseFloat(et_alpha3.getText().toString());
    				long durationMillis = Long.parseLong(et_alpha1.getText()
    						.toString());
    
    				iv_show.startAnimation(AnimationTools.alphaAnimation(fromAlpha,
    						toAlpha, durationMillis));
    			}
    			break;
    		case R.id.rotateButton:
    			if (et_rotate1.getText().toString().isEmpty()
    					|| et_rotate2.getText().toString().isEmpty()
    					|| et_rotate3.getText().toString().isEmpty()
    					|| et_rotate4.getText().toString().isEmpty()
    					|| et_rotate5.getText().toString().isEmpty())
    				Toast.makeText(MainActivity.this, "旋转内容未填完整", 0).show();
    			else {
    				float fromDegrees = Float.parseFloat(et_rotate1.getText()
    						.toString());
    				float toDegrees = Float.parseFloat(et_rotate2.getText()
    						.toString());
    				float pivotXValue = Float.parseFloat(et_rotate3.getText()
    						.toString());
    				float pivotYValue = Float.parseFloat(et_rotate4.getText()
    						.toString());
    				long rdurationMillis = Long.parseLong(et_rotate5.getText()
    						.toString());
    				iv_show.startAnimation(AnimationTools.rotateAnimation(
    						fromDegrees, toDegrees, pivotXValue, pivotYValue,
    						rdurationMillis));
    			}
    			break;
    		case R.id.scaleButton:
    			if (et_scale1.getText().toString().isEmpty()
    					|| et_scale2.getText().toString().isEmpty()
    					|| et_scale3.getText().toString().isEmpty()
    					|| et_scale4.getText().toString().isEmpty()
    					|| et_scale5.getText().toString().isEmpty()
    					|| et_scale6.getText().toString().isEmpty()
    					|| et_scale7.getText().toString().isEmpty())
    				Toast.makeText(MainActivity.this, "收缩内容未填完整", 0).show();
    			else {
    				float fromX = Float.parseFloat(et_scale1.getText().toString());
    				float toX = Float.parseFloat(et_scale2.getText().toString());
    				float fromY = Float.parseFloat(et_scale3.getText().toString());
    				float toY = Float.parseFloat(et_scale4.getText().toString());
    				float spivotXValue = Float.parseFloat(et_scale5.getText()
    						.toString());
    				float spivotYValue = Float.parseFloat(et_scale6.getText()
    						.toString());
    				long sdurationMillis = Long.parseLong(et_scale7.getText()
    						.toString());
    				iv_show.startAnimation(AnimationTools.scaleAnimation(fromX,
    						toX, fromY, toY, spivotXValue, spivotYValue,
    						sdurationMillis));
    			}
    			break;
    		case R.id.translateButton:
    			if (et_trans1.getText().toString().isEmpty()
    					|| et_trans2.getText().toString().isEmpty()
    					|| et_trans3.getText().toString().isEmpty()
    					|| et_trans4.getText().toString().isEmpty()
    					|| et_trans5.getText().toString().isEmpty())
    				Toast.makeText(MainActivity.this, "收缩内容未填完整", 0).show();
    			else {
    				float fromXValue = Float.parseFloat(et_trans1.getText()
    						.toString());
    				float toXValue = Float.parseFloat(et_trans2.getText()
    						.toString());
    				float fromYValue = Float.parseFloat(et_trans3.getText()
    						.toString());
    				float toYValue = Float.parseFloat(et_trans4.getText()
    						.toString());
    				long tsdurationMillis = Long.parseLong(et_trans5.getText()
    						.toString());
    				iv_show.startAnimation(AnimationTools.translateAnimation(
    						fromXValue, toXValue, fromYValue, toYValue,
    						tsdurationMillis));
    			}
    			break;
    		default:
    			break;
    		}
    
    	}
    
    }
    


     源码下载地址:CSDN(暂未上传)

     

     
    展开全文
  • animation动画库 + animation用法

    千次阅读 2018-09-10 05:43:24
    动画库 1. animation.css https://daneden.github.io/animate.css/ 简单使用时,f12 审查元素 .cls 就可以查找对应的animation。 这个库最简单。 2. hover.css  http://ianlunn.github.io/Hover/ f12审查...
  • CSS3的animation属性可以像Flash制作动画一样,通过控制关键帧来控制动画的每一步,实现更为复杂的动画效果。ainimation实现动画效果主要由两部分组成: 1)通过类似Flash动画中的帧来声明一个动画; 2)在animation...
  • 用css3的animation完成一个动画,当只有这个动画完成时才执行令一个事件,比如让动画保持在终止的状态或其他一些事件。我们该怎么办呢。 ...当-webkit-animation动画结束时有一个webkitAnimatio...
  • 让css animation 动画停在结束的时候

    千次阅读 2020-10-07 15:48:19
    让css animation 动画停在结束得的时候 使用css animation的时候经常会想让动画停留在最后一帧,比如鼠标移上的的时候希望往上移动一点,鼠标移开的时候希望再往回移; 可以使用 animation-fill-mode:forwards;进行...
  • 我们可以利用鼠标的hover伪类实现动画的暂停 div:hover { animation-play-state:...W3C animation动画暂停 顺便说一下animation清除动画 div:hover { animation-duration: 0s; } W3C animation动画有介绍 ...
  • 利用Unity官方Animation示例里的两种动画节点,来实现外部输入index值时,自动将目前动画clip自动混合过度到指定index动画clip的功能。
  • 在Flutter Animation动画开发之——最简单的动画入门这篇文章中我们介绍了最简单的动画开发流程 今天我们在该动画的基础上添加动画曲线,默认情况下动画是线性的,可以理解为变化是匀速的,设置动画曲线可以设置...
  • Unity中Animation动画的创建

    千次阅读 2020-10-14 22:09:58
    1.首次创建Animation动画: (1) 把Sprite直接拖到Hierarchy面板; (2) 选中拖上去的Sprite,然后Windows->Animation或者直接Ctrl+ 6,弹出Animation面板; (3) 在Animation面板中有个Create按钮,点击创建...
  • -webkit-animation动画,CSS动画的使用

    千次阅读 2019-07-05 11:18:24
    web加载动画,CSS动画 今天由于工作需要,在Git上面拿到一个微信小程序,导入后随便点点,他的loading动画吸引到我了。根据源码,搭配blog,w3c,一点一点学习怎么设计的这个loading。 1.效果图 四周小方块不停的...
  • CSS3的animation动画设置无效

    千次阅读 2020-02-24 14:16:04
    元素得设置有 position:relative; 或 position:absolute;
  • Matplotlib之animation动画

    千次阅读 2019-07-27 21:53:40
    animation画一个y=sin(x)的动画函数。 代码如下: from numpy import * import matplotlib.pyplot as plt from matplotlib import animation fig,ax=plt.subplots() #相当于fig=plt.figure(),ax=plt.subplot()...
  • 监听animation动画事件

    千次阅读 2016-06-02 15:57:40
    当你需要在某个动画开始或者结束时,去触发某一个事件,... 1、-webkit-animation动画其实有三个事件:  开始事件 webkitAnimationStart  结束事件 webkitAnimationEnd  重复运动事件 webkitAnimationIteration
  • 本文来源于 CSS animation动画之animation-fill-mode特性 问题 css属性animation动画可以轻松地给页面带来很炫很酷的效果,但是有时候我们会遇到这个问题,动画结束后css状态会返回到初始状态,那么这并不是我们...
  • 我们知道AnimationController.forward()可以正向播放动画,如果要反向播放动画,可以调用AnimationController.reverse() 踩坑 马上写段代码验证一下,如下代码演示了一个绿色的方块,方向执行动画,大小从200缩小...
  • TimeLine及Animation动画的坑

    千次阅读 2020-07-09 15:06:35
    TimeLine只支持新版的animation控件制作的动画animation在2018.3版本更新了) 如果是旧版的animation,右键Inspector调出Debug界面,不勾选Legacy(中文版为“旧版”),然后再次右键点击Inspector切换为原来的...
  • Unity创建Animation动画无法播放问题

    万次阅读 2019-05-29 14:17:19
    前提:我是要使用animation的方式去播放动画,而不是animator状态机;是针对unity自己制作的动画,而不是外部导入进来的动画。 发现一个问题,我在unity中给一个cube创建一个animation后,会自动创建一个animator...
  • Unity之Animation动画

    千次阅读 2017-12-22 14:56:56
    Unity之Animation动画 Unity之Animation绘制动画 这篇文章做最简单的动画,让一个立方体从左边移动到右边。 1.创建一个Unity的新工程,名为TestAnimation,点击Create And Open按键,打开工程。 2.进入工程...
  • css3 animation动画

    千次阅读 2020-06-07 01:16:29
    animation <a href="javascript:;" class="more"><img src="images/00-more.png" alt=""></a> @keyframes more{ from { transform: translateY(-30px); } to { transform: translateY(0px...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 163,615
精华内容 65,446
关键字:

animation动画