Android 3.0系统上 解密GMail动画

3.0以前,android支持两种动画模式,tween animation,frame animation,在android3.0中又引入了一个新的动画系统:property animation,这三种动画模式在SDK中被称为property animation,view animation,drawable animation。

这篇文章主要使用ObjectAnimator来实现动画的效果。

使用ObjectAnimator这个对象限制性比较多,要满足一定的条件才可以使用,不然动画没有效果。ObjectAnimator继承ValueAnimator,其实就是指定一个对象以及该对象的一个属性,当属性值计算完成自动设置该对象的相关属性,即完成propety Antimation的全部两个操作。

条件为:

1.对象应该有get<属性名> ;set<属性名>方法。

2.ofInt或者ofFloat方法第一个参数是对象名,第二个参数是属性值,后面的参数为可变参数,如果可变参数为1个值,会假定目的值,获取当前值会调用get<属性值>这个方法。

这边用一个简单的例子实现这个动画

首先有3个xml,一个主Activity的main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/l1"
    android:baselineAligned="false" >
    <FrameLayout
        android:id="@+id/fragment1"
        android:layout_width="300dp"
        android:background="#FF0000"
        android:layout_height="fill_parent" />
    <FrameLayout
        android:id="@+id/fragment2"
        android:layout_width="980dp"
        android:background="#00FF00"
        android:layout_height="fill_parent" />
</LinearLayout>
然后定义一个f1.xml和f2.xml作为fragment1和fragment2的布局,然后替换main.xml中的framelayout1和framgelayout2。fragment的操作,大家在网上一搜一大片,怎么使用就不讲了。

f1.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#30000000"
    android:gravity="center"
    android:baselineAligned="false" >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="30sp"
        android:text="F1" />
</LinearLayout>

f2.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center"
    android:baselineAligned="false" >
    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="go" />
</LinearLayout>
fragment1.java

public class Fragment1 extends Fragment {
    public static Fragment1 newInstance() {
        return new Fragment1();
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.f1, container, false);
        return root;
    }
}
fragment2.java

public class Fragment2 extends Fragment {

    private WeakReference<FragmentResultListener> mFragmentResultListenerRef;

    public interface FragmentResultListener {
        public void onBtnClick();
    }

    public static Fragment2 newInstance(FragmentResultListener listener) {
        Fragment2 f = new Fragment2();
        f.setFragmentResultListener(listener);
        return f;
    }

    private void setFragmentResultListener(FragmentResultListener listener) {
        mFragmentResultListenerRef = new WeakReference<FragmentResultListener>(listener);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.f2, container, false);
        root.findViewById(R.id.btn).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                FragmentResultListener fragmentResultListener = mFragmentResultListenerRef.get();
                if (fragmentResultListener != null) {
                    fragmentResultListener.onBtnClick();
                }
            }
        });
        return root;
    }
}

这边实现动画的操作需要点击fragment2中的按钮,所以这边使用了回调,先在fragment2中定义个点击的接口,然后再把接口的方法放在按钮的监听事件里面,然后外边调用的时候实现接口的操作,把接口对象传递过来就ok了。

这边是主要的程序,也是主Acitvity的实现逻辑,动画的定义,都在里面。

public class FragmentAnimationTestActivity extends Activity implements Fragment2.FragmentResultListener {

    private static final TimeInterpolator sCollapseInterpolator = new DecelerateInterpolator(2.5F);

    private View mPanel1;
    private View mPanel2;
    private View mLayout;

    boolean isCollapsed;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mLayout = findViewById(R.id.l1);
        mPanel1 = findViewById(R.id.fragment1);
        mPanel2 = findViewById(R.id.fragment2);
        FragmentTransaction ft = getFragmentManager().beginTransaction();
        ft.replace(R.id.fragment1, Fragment1.newInstance(), "f1");
        ft.replace(R.id.fragment2, Fragment2.newInstance(this), "f2");
        ft.commit();
    }

    public int getPanelLeft() {
        return ((ViewGroup.MarginLayoutParams) mLayout.getLayoutParams()).leftMargin;
    }

    public void setPanelLeft(int paramInt) {
        ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) mLayout.getLayoutParams();
        lp.leftMargin = paramInt;
        mLayout.setLayoutParams(lp);
    }

    public int getPanel2W() {
        return ((ViewGroup.MarginLayoutParams) mPanel2.getLayoutParams()).width;
    }

    public void setPanel2W(int paramInt) {
        ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) mPanel2.getLayoutParams();
        lp.width = paramInt;
        mPanel2.setLayoutParams(lp);
    }

    @Override
    public void onBtnClick() {
        if (isCollapsed) {
            PropertyValuesHolder[] arrayOfPropertyValuesHolder = new PropertyValuesHolder[2];
            arrayOfPropertyValuesHolder[0] = PropertyValuesHolder.ofInt("PanelLeft", -300, 0);
            arrayOfPropertyValuesHolder[1] = PropertyValuesHolder.ofInt("Panel2W", 1280, 980);
            ObjectAnimator localObjectAnimator = ObjectAnimator.ofPropertyValuesHolder(this,
                    arrayOfPropertyValuesHolder).setDuration(400);
            localObjectAnimator.setInterpolator(sCollapseInterpolator);
            localObjectAnimator.start();
        } else {
            PropertyValuesHolder[] arrayOfPropertyValuesHolder = new PropertyValuesHolder[2];
            arrayOfPropertyValuesHolder[0] = PropertyValuesHolder.ofInt("PanelLeft", 0, -300);
            arrayOfPropertyValuesHolder[1] = PropertyValuesHolder.ofInt("Panel2W", 980, 1280);
            ObjectAnimator localObjectAnimator = ObjectAnimator.ofPropertyValuesHolder(this,
                    arrayOfPropertyValuesHolder).setDuration(400);
            localObjectAnimator.setInterpolator(sCollapseInterpolator);
            localObjectAnimator.start();
        }
        isCollapsed = !isCollapsed;
    }

上面主要使用了ObjectAnimator动画对象,其中ofInt使用了“panelLef'和”panel2W“这2个属性,这2个属性的set和get方法以及ofInt的使用。条件已经满足可以使用ObjectAnimaor对象。

上面还使用一个对象TimeInterplator,这个属相定义了属性值变化的范围,如线性均匀变化,开始慢然后快等等。timeInterplator是propertyAnimation中使用,在这边列举一些简单的实现对象。

  • AccelerateInterpolator        加速,开始时慢中间加速
  • DecelerateInterpolator       减速,开始时快然后减速
  • AccelerateDecelerateInterolator  先加速后减速,开始结束时慢,中间加速
  • AnticipateInterpolator      反向 ,先向相反方向改变一段再加速播放
  • AnticipateOvershootInterpolator  反向加超越,先向相反方向改变,再加速播放,会超出目的值然后缓慢移动至目的值
  • BounceInterpolator       跳跃,快到目的值时值会跳跃,如目的值100,后面的值可能依次为85,77,70,80,90,100
  • CycleIinterpolator         循环,动画循环一定次数,值的改变为一正弦函数:Math.sin(2 * mCycles * Math.PI * input)
  • LinearInterpolator        线性,线性均匀改变
  • OvershottInterpolator        超越,最后超出目的值然后缓慢改变到目的值
  • TimeInterpolator          一个接口,允许你自定义interpolator,以上几个都是实现了这个接口

    后面再把这三种动画对象的区别讲解下吧。

    相关知识参考:

    http://www.open-open.com/lib/view/open1329994048671.html

    http://android.amberfog.com/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值