Android:使用ObjectAnimator将视图的分数值转换为视图的维度

看起来,旧的视图animation( translatescale等)不再被AnimationInflater接受,至less在ICS中是如此。 我在4.0.4中阅读了它的代码,它明确地期望只有XML元素setobjectAnimatoranimator

即使http://developer.android.com/guide/topics/resources/animation-resource.html上的文档继续包含视图animation,它们似乎也被弃用了。 尝试使用它们会导致,例如,错误java.lang.RuntimeException: Unknown animator name: translate

因此,有必要使用Android的ObjectAnimator 。 但是,它不接受与其自身或其父级(例如translationX宽度)相关联的维度的分数值,如旧视图animation以"75%p"的forms所做的那样。

在运行时手动构造ObjectAnimator ,通过编程获取Fragment的大小是不可行的,因为FragmentTransaction只接受由resid指定的声明animation。

我的目标是翻译屏幕上填满整个活动(我基本上是做两个片段之间的转换过渡)的片段。 这是现有的TranslationAnimation实现( slide_in_right.xml ,它与其对应的slide_out_left.xml由于某种原因没有在android.R.anim公开,因此我必须在我的代码库中复制它们):

 <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:fromXDelta="100%p" android:toXDelta="0" android:duration="@android:integer/config_mediumAnimTime"/> </set> 

我的API级别设置为14。

谢谢!

实际上对象animation师接受分数值。 但是,也许你并不了解objectAnimator的底层概念,或者更普遍的是一个值的animation。 一个值animation会animation与属性相关的值(如颜色,屏幕上的位置(X,Y),alpha参数或任何你想要的)。 要创build这样的属性(在你的情况xFraction和yFraction),你需要build立自己的getter和setter关联到这个属性名称。 比方说,你要将FrameLayout从整个屏幕大小的0%翻译到25%。 然后,您需要构build一个包装FrameLayout对象的自定义视图,并编写您的getter和setter。

 public class SlidingFrameLayout extends FrameLayout { private static final String TAG = SlidingFrameLayout.class.getName(); public SlidingFrameLayout(Context context) { super(context); } public SlidingFrameLayout(Context context, AttributeSet attrs) { super(context, attrs); } public float getXFraction() { int width = getWindowManager().getDefaultDisplay().getWidth(); return (width == 0) ? 0 : getX() / (float) width; } public void setXFraction(float xFraction) { int width = getWindowManager().getDefaultDisplay().getWidth(); setX((width > 0) ? (xFraction * width) : 0); } } 

然后,您可以使用xml方法来声明将xFraction放置在属性xml属性下的对象animation器,并使用AnimatorInflater

 <?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:propertyName="xFraction" android:valueType="floatType" android:valueFrom="0" android:valueTo="0.25" android:duration="500"/> 

或者你可以只使用java行代码

 ObjectAnimator oa = ObjectAnimator.ofFloat(menuFragmentContainer, "xFraction", 0, 0.25f); 

希望它可以帮助你!

奥利维尔

FragmentTransaction Android SDK实现需要一个Animator ,但由于某些不明确的原因,支持库实现需要一个Animation ,如果使用支持库中的Fragment实现,则您的翻译animation将起作用

对于那些试图创build视图animation(如translatescale人来说,这是一个重要的陷阱

属性animation位于名为“ animator ”的目录中: res/animator/filename.xml

但是,视图animation必须放在一个名为“ anim ”的目录中: res/anim/filename.xml

我首先将视图animation放在“animator”文件夹中,并对Android Studio抱怨翻译不是一个有效的元素。 所以, ,视图animation不被弃用。 他们只是有一些令人困惑的原因,他们自己的位置。

这里是完整的工作示例(按接受答案作者的描述工作)。

按下button在2个片段A和B之间切换(通过从右向左滑动animation)。 这些片段只是具有不同背景的愚蠢文本(AAAAAA和BBBBB)。

MainActivity.java

 package com.example.slidetrans; import android.app.Activity; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity { private static final String TAG = "Main"; boolean showingA = true; Button button; A a; B b; private void incarnate(FragmentManager fm){ int layoutId = R.id.frame; boolean fragmentWasNull = false; Fragment f = fm.findFragmentById(layoutId); if (f == null){ Log.i(TAG, "fragment is null"); if (showingA){ f = a = new A(); } else { f = b = new B(); } fragmentWasNull = true; } else { Log.i(TAG, "fragment is not null"); showingA = (f instanceof A); updateButtonText(); } if (fragmentWasNull){ FragmentTransaction ft = fm.beginTransaction(); ft.add(layoutId, showingA ? a : b, "main").commit(); } } private void updateButtonText(){ button.setText(showingA ? "slide in B" : "slide in A"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); FragmentManager fm = getFragmentManager(); button = (Button)findViewById(R.id.button); incarnate(fm); OnClickListener listener = new OnClickListener() { @Override public void onClick(View v) { FragmentManager fm = getFragmentManager(); FragmentTransaction transaction = fm.beginTransaction(); transaction.setCustomAnimations(R.anim.in, R.anim.out); transaction.replace(R.id.frame, showingA ? new B() : new A()).commit(); showingA = !showingA; updateButtonText(); } }; button.setOnClickListener(listener); } } 

LL.java

 package com.example.slidetrans; import android.content.Context; import android.util.AttributeSet; import android.widget.LinearLayout; public class LL extends LinearLayout { public LL(Context context) { super(context); } public LL(Context context, AttributeSet attrs) { super(context, attrs); } public float getXFraction() { final int width = getWidth(); if (width != 0) return getX() / getWidth(); else return getX(); } public void setXFraction(float xFraction) { final int width = getWidth(); float newWidth = (width > 0) ? (xFraction * width) : -9999; setX(newWidth); } } 

main.xml(布局)

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="slide in B" /> <FrameLayout android:id="@+id/frame" android:layout_width="match_parent" android:layout_height="match_parent" > </FrameLayout> </LinearLayout> 

a.xml(布局)

 <?xml version="1.0" encoding="utf-8"?> <com.example.slidetrans.LL xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#00FF00" > <TextView android:id="@+id/aText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="AAAAAAAAAAAAAAAAAA" android:textSize="30sp" android:textStyle="bold" /> </com.example.slidetrans.LL> 

b.xml(布局)

 <?xml version="1.0" encoding="utf-8"?> <com.example.slidetrans.LL xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#FFFF00" > <TextView android:id="@+id/bText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="30sp" android:textStyle="bold" android:text="BBBBBBBBBB" /> </com.example.slidetrans.LL> 

in.xml(anim)

 <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:duration="500" android:interpolator="@android:anim/linear_interpolator" android:propertyName="xFraction" android:valueFrom="1.0" android:valueTo="0.0" android:valueType="floatType" /> </set> 

out.xml(anim)

 <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:duration="500" android:interpolator="@android:anim/linear_interpolator" android:propertyName="xFraction" android:valueFrom="0.0" android:valueTo="-1.0" android:valueType="floatType" /> </set> 

视图animation不被弃用。 如果您正在使用Eclipse,则可以在创build新的Android XML文件时将它们作为资源types在补间animation下find。