View的滑动(二)

实现的方式

    1.使用scrollTo 或者 scrollBy

    2.使用动画

    3. 改变布局参数


三种实现方式对比

1.scrollToor scrollBy只会改变View里面的子View的位置,不会改变View的位置

2.动画:属性动画是真正的改变View的位置,但只有3.0以后的版本才支持属性动画,View动画只是改变View的影像

3.改变布局参数实现起来需要考虑对其他View位置的影响


实现

使用scrollTo 或者 scrollBy

scrollTo是基于所传递参数的绝对滑动 和 scrollBy是基于当前位置的相对滑动

   publicvoidscrollBy(int x,int y) {

        scrollTo(mScrollX + x,mScrollY + y);

}

可以看出scrollBy就是调用了scrollTo的实现相对滑动

另外需要注意的是scrollTo和scrollBy只能将View的内容进行移动,并不能将View本身进行移动。不会改变View在布局中的位置

 

relative1.scrollTo(0,-100);

仅仅移动relative1里面的View。

 

并且scrollTo(int x,int y)

参数x为正时 view向左移动

参数y为正时 view向上移动

反之,右,下。

 

ScrollTo和scrollBy这种方式,可以比较方便的实现滑动效果并且不影响内部元素的单击事件,但他的缺点就是不能滑动View本身,只能滑动View包含的View。

 

上述同样限制这种方式的使用范围


直接使用ScrollTo或者scrollby View会硬生生的瞬间完成滑动,而我们大多数时间是希望有一个弹性滑动的效果。

 

实现弹性滑动方式:

   使用Scroller

   Scrollerscroller = new Scroller(mContext);

//Interpolator插值器

Scrollerscroller = new Scroller(mContext, interpolator);

  

   //缓慢滑动动指定的位置

   Privatevoid smoothScrollTo(int destX,int destY){

      intscrollX = getScrollX();

      intdeltaX = destX – scrollX;

//1000ms内滑动向destX,效果慢慢滑动

mScoller.starScroll(scrollX,0,deltaX,0,1000);

invalidate();

}

 

//必须重写的方法

@Override

Public void computeScroll(){

  If(mScroller.computeScrollOffset()){

     scrollTo(mScroller.getCurrX(),mscroller.getCurrY());

     postInvalidate();

}

}

 

如果分析Scroller的源码可以发现,Scroller本身并没有实现View 的滑动,她需要配合View的computeScroll方法才能完成弹性滑动的效果。computeScrollOffset根据时间流逝计算当前的scrollX和scrollY然后不断的调用ScrollTo,然后重绘。

 

借用动画

动画本身就是一个渐变的过程,因此通过动画当然可以实现弹性的滑动

ValueAnimator va = ObjectAnimator.ofInt(0,100).setDuration(500).start();

va.addUpdateListener(newAnimatorUpdateListener(){

@override

publicvoid onAnimationUpdate(ValueAnimator animator){

float flag = animator.getAnimatorFraction();

mButton1.scrollTo(startX+(int )(deltaX*flag),0);

}

});

   动画就是充当一个计时工具。

 

   自定义延时策略

final Runnable run = new Runnable() {

                   @Override

                   publicvoid run() {

                      count++;

                      floatflag = count/30f;

                      relative1.scrollTo(0,(int) (-100*flag));

                   }

                };

 

                Timertimer = new Timer();

                timer.schedule(newTimerTask() {

                   @Override

                   publicvoid run() {

                      relative1.post(run);

                   }

                },0, 10);

使用线程计时实现滑动。

 

使用动画

View动画和属性动画的最大区别就是 View动画只是改变View的影像的位置,而属性动画改变的是View的实际位置

 

也就是说 如果一个button使用View动画后,点击动画后的位置的button不会触发事件,而点击butotn原来的位置则可以触发事件。而属性动画不存在这样的情况。

所以View动画只适用于没有事件绑定的View。当然可以人工处理比如:隐藏原来位置的view,在影像的位置生成新view并绑定事件(太麻烦)

 

属性动画没有什么缺点,但是只有android3.0以后支持

 

Android3.0以前想使用属性动画的话,可以引入nineoldandroids ,但是只是兼容代码,本质上在3.0以前还是属于view动画。

 

View动画的四种变换效果对应 Animation的四个子类:

TranslateAnimation

ScaleAnimation

RotateAnimation

AlphaAnimation

View动画可以动态创建也可以使用xml定义动画 一般会使用xml的形式

在anim文件夹下:

<?xmlversion="1.0"encoding="utf-8"?>

<setxmlns:android="http://schemas.android.com/apk/res/android"

    android:fillAfter="true"

    android:zAdjustment="normal"

    >

   <translate

        android:duration="500"

        android:fromXDelta="0"

        android:fromYDelta="0"

        android:interpolator="@android:anim/linear_interpolator"

        android:toXDelta="100"

        android:toYDelta="100"

        />

</set>

常用的属性效果需要多练习

在代码中使用:

Animation animation =AnimationUtils.loadAnimation(GesturetestActivity.this, R.anim.test_aaim);

button1.setAnimation(animation);

 

帧动画

drawable目录下

<animation-list>

Btn.setbackground(animation-list);

AnimationDrawable =  Btn.getBackground();

AnimationDrawable.start;

 

 

LayoutAnimation

作用于ViewGroup item的动画

Anim文件夹下

<layoutAnimation>

可以直接 xml引用android:layoutAnimation="@anim/anim_layout"

也可以

animation = AnimationUtil.loadAnimation

contorller = new LayoutAnimationCotroler(animation)

contorller.set

listView.setLayoutAnimation(controller);

 

Activity切换

overrideRedingTransition在startAcitivity 或者 finish之后调用

Fragment切换

FragmentTransaction  setCustomAnimations


属性动画

 

API11新加入的特性  

API11以下 支持库:nineoldandroids本质还是View动画

常用的几个动画类:

ValueAnimator

ObjectAnimator

AnimatorSet

ObjectAnimator继承自ValueAnimator,AnimatorSet是动画集合

 

ObjectAnimator anim =ObjectAnimator.ofFloat(button1,"translationY", 0,100).setDuration(1000);

            anim.setInterpolator(new BounceInterpolator());

            anim.setEvaluator(new FloatEvaluator());

            anim.addListener(newAnimatorListenerAdapter() {

                @Override

                public void onAnimationEnd(Animatoranimation) {

                   // TODO Auto-generated method stub

                   super.onAnimationEnd(animation);

                }

            });

            anim.start();

 

 

ObjectAnimator colorAnim =ObjectAnimator.ofInt(button1,"backgroundColor", Color.RED,Color.GREEN).setDuration(3000);

            colorAnim.setRepeatCount(20);

            colorAnim.setRepeatMode(ValueAnimator.REVERSE);

            colorAnim.setEvaluator(new ArgbEvaluator());

            //colorAnim.setInterpolator(new BounceInterpolator());

            colorAnim.start();

 

   AnimatorSetset = newAnimatorSet();

      set.playTogether(

                   ObjectAnimator.ofFloat(button1,"rotationY",0,180),

                   ObjectAnimator.ofFloat(button1,"scale",1,2),

                   ObjectAnimator.ofFloat(button1,"translationX",0,200),

                   ObjectAnimator.ofFloat(button1,"translationY",0,200),

                   ObjectAnimator.ofFloat(button1,"alpha",1,0.25f,1)

                   );

      set.setDuration(3000).start();

 

也可以在animator 目录下定义xml 实现属性动画

<set>

<objectAnimator>

<animator>

</set>

 

AnimatorSet set =AnimatorInflate.loadAnimator(myContext,R.anim.property);

set.setTarget(mbt);

set .start();  

开发中属性动画很少会使用xml实现

 

使用属性动画对任意属性动画

属性动画要求动画作用的对象提供该属性的get和set方法,属性动画根据外界传递的该属性的初始值和最终值,以动画的效果多次去调用set方法,每次传递给set方法的值都不一样,确切的说是随着时间的推移,所传递的值越来越接近最终值。

所以我们对object的属性abc做动画,object就必须提供setAbc方法和getAbc方法

setAbc同时可以自己更新UI

当我们需要对一个不满足条件的view使用属性动画时,可以用一个原始对象,间接的提供get和set方法

ObjectAnimator.ofInt(newwrapper(view),"width",500).setduration(500).start();

 

private static class wrapper{

 private view t;

 wrapper( View view){

  t =view

  }

 public int getT(){

   return t.getLayoutParams().width;

  }

 public int setT(){

   t.getLayoutParams().width = width;

   t.requestLayout();

  }

}

 

注意

帧动画容易出现oom

Activity退出时停止动画,防止内存泄露

3.0属性动画的兼容问题

View动画是对view的影像的动画,并不是真正的改变view的状态

尽量实用dp


改变布局参数

MarginLayoutParams params =(MarginLayoutParams) button1.getLayoutParams();

   params.width += 100;

   params.height +=100;

   params.topMargin+=100;

   button1.requestLayout();

需要处理给其他View的位置带来的影响,只有在特殊的时候使用。


补充

 插值器和估值器

TimeInterPolator

时间插值器,根据时间流逝的百分比来计算出当前属性值改变的百分比,系统预置的有LinearInterpolator AccelerateDecelerateInterpolator 等等

 

TypeEvaluator

类型估值算法

根据当前属性改变的百分比计算改变后的属性值,系统预置的有IntEvaluatorFloatEvaluator ArgbEvaluator(针对color  比较有实用)

 

他们是实现非匀速动画的重要手段         

本文算是任玉刚大神《android开发艺术探索》的阅读笔记。感谢大神



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值