学习知乎日报---day4

  • 自定义ReavlBackground的实现

    今天应该只是完成了这一部分的学习,还是有些不明白的地方,忘有好心认识可以指教。非常感线伯乐在线上的一篇文章(http://android.jobbole.com/81113/),有兴趣的朋友可以看一下。

    首先今天要完成的是,切换页面的动画,这个动画属于涟漪状,一般是圆形的,但是如果不喜欢可以任意修改,方法实在自定义的View里重写Ondraw()方法。
    实现 ReavlBackgroundview 必须实现以下几点:

  • Reveal动画必须从点击的那个点开始

  • 我们想要掌控动画的状态(未开始,开始了,结束)

  • 我们还要能主动结束动画

看一下代码是怎么实现的吧:

    //动画的状态(未开始,开始了,结束)
    public static final int STATE_NOT_STARTED = 0;
    public  static final int STATE_FILE_STARTED = 1;
    public  static final int STATE_FINISHED = 2;
    //必须从点击的那个点开始
    public void startFromLocation(int[] tapLocationOnScreen){
        chageState(STATE_FILE_STARTED);
        startLocationX = tapLocationOnScreen[0];
        startLocationY = tapLocationOnScreen[1];
        //translate 应该是一个渐变的效果
        revealAnimator = ObjectAnimator.ofInt(this,"currentRadius",getWidth()+getHeight())
                .setDuration(FILL_TIME);
        revealAnimator.setInterpolator(INTERPOLATOR);
        revealAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                chageState(STATE_FINISHED);
            }
        });
        revealAnimator.start();
        }
//还要能主动结束动画
        public void setFinishedFrame(){
        chageState(STATE_FINISHED);
        invalidate();
        }

由于调用了 invalidate()方法所以要重写onDraw()方法,不过这个并不光是因为这个原因,要重写onDraw(),最重要是因为,我们定义的涟漪效果需要开始是矩形,推出的时候是圆形。

@Override
    protected void onDraw(Canvas canvas) {
        if (state == STATE_FINISHED){
            canvas.drawRect(0, 0, getWidth(), getHeight(), fillPaint);
        }else {
                                        canvas.drawCircle(startLocationX,startLocationY,
                                                      currentRedius,fillPaint);
        }
    }

2. ObjectAnimator
实现涟漪动画的时候用到了它,这个是android 3.0 以后加入的动画,叫做属性动画。不同于补间动画只能改变 alpha,scale,rotate,translate,
例如我的程序里用到到位移动画:

 revealAnimator =ObjectAnimator.ofInt(this,
 getWidth()+getHeight())
            .setDuration(FILL_TIME);
        revealAnimator.setInterpolator(INTERPOLATOR);
        revealAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                chageState(STATE_FINISHED);
            }
        });

还需要写有个接口,当动画状态变化的时候调用。

public static interface OnStateChangeListener {
        void onStateChange(int state);
    }

具体代码在这里:reavalbackground

3. 关于何时调用onDraw()
View的绘制流程,首先调用onMeasure() ,主要作用:为整个View树计算实际的大小,即设置实际的高(对应属性:mMeasuredHeight)和宽(对应属性:mMeasureWidth),每个View的控件的实际宽高都是由父视图和本身视图决定的。然后调用onlayout()主要作用 :为将整个根据子视图的大小以及布局参数将View树放到合适的位置上。,最后调用onDraw() 主要作用:由ViewRoot对象的performTraversals()方法调用draw()方法发起绘制该View树,值得注意的是每次发起绘图时,并不会重新绘制每个View树的视图,而只会重新绘制那些“需要重绘”的视图,View类内部变量包含了一个标志位DRAWN,当该视图需要重绘时,就会为该View添加该标志位。
invalidate()方法 :
说明:请求重绘View树,即draw()过程,假如视图发生大小没有变化就不会调用layout()过程,并且只绘制那些“需要重绘的”
视图,即谁(View的话,只绘制该View ;ViewGroup,则绘制整个ViewGroup)请求invalidate()方法,就绘制该视图。
一般引起invalidate()操作的函数如下:

  • 1、直接调用invalidate()方法,请求重新draw(),但只会绘制调用者本身。

  • 2、setSelection()方法 :请求重新draw(),但只会绘制调用者本身。

  • 3、setVisibility()方法 : 当View可视状态在INVISIBLE转换VISIBLE时,会间接调用invalidate()方法,
    继而绘制该View。

  • 4 、setEnabled()方法 : 请求重新draw(),但不会重新绘制任何视图包括该调用者本身。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值