Android - 在同一个 XML 文件上制作翻译和 objectAnimator

Posted

技术标签:

【中文标题】Android - 在同一个 XML 文件上制作翻译和 objectAnimator【英文标题】:Android - Making translations and objectAnimator on the same XML file 【发布时间】:2013-04-20 14:00:27 【问题描述】:

我一直在尝试制作 3D 立方体旋转效果,同时从一个片段滑到另一个片段。 首先,我使用FragmentTransaction.setCustomAnimations(...) 调用翻译效果(在 XML 上),然后,在打开/关闭片段时,我正在使用 Camera 类进行旋转。

这工作得很好,但似乎我也有(不要问我为什么)只使用 XML 文件来使用所有这些动画。经过长时间的搜索,我发现我应该使用 objectAnimator 进行旋转。

按照谷歌示例,我设法制作了翻转动画。现在我需要翻译片段,使它们滑入和滑出。似乎我不能在同一个 XML 文件上使用 objectAnimator 和翻译效果。由于出现这个错误:

java.lang.RuntimeException: Unknown animator name: translate at (...)

关于如何制作滑动效果和同时使用 objectAnimator 有什么想法吗?

感谢您的宝贵时间!

我一直在使用的代码:

card_flip_right_in.xml

<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <!-- Before rotating, immediately set the alpha to 0. -->
    <objectAnimator
        android:duration="0"
        android:propertyName="alpha"
        android:valueFrom="1.0"
        android:valueTo="0.0" />

    <!-- Rotate. -->
    <objectAnimator
        android:duration="@integer/card_flip_time_full"
        android:interpolator="@android:interpolator/accelerate_decelerate"
        android:propertyName="rotationY"
        android:valueFrom="180"
        android:valueTo="0" />

    <!-- Half-way through the rotation (see startOffset), set the alpha to 1. -->
    <objectAnimator
        android:duration="1"
        android:propertyName="alpha"
        android:startOffset="@integer/card_flip_time_half"
        android:valueFrom="0.0"
        android:valueTo="1.0" />

</set>

片段调用另一个片段:(立方体旋转应该在这 2 之间可见)

private void launchArticle(int prev, int pos)
        ArticleFragment newFragment = new ArticleFragment();
        Bundle args = new Bundle();
        args.putString("pos", pos);
        args.putInt("prev", prev);
        newFragment.setArguments(args);
        android.app.FragmentTransaction transaction = getFragmentManager().beginTransaction();
        Fragment currFrag = (Fragment)getFragmentManager().findFragmentById(R.id.headlines_fragment);
        if (currFrag != null) 
                transaction.hide(currFrag);
        
        transaction.setCustomAnimations(
                R.animator.card_flip_right_in,
                R.animator.card_flip_right_out,
                R.animator.card_flip_left_in,
                R.animator.card_flip_left_out
                );

        transaction.replace(R.id.fragment_container, newFragment, pos);
        transaction.addToBackStack(null);

        transaction.commit();

更新:

我已经设法使用一个扩展我正在使用的片段的框架布局的类来解决之前的问题

SlidingFrameLayout.java

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()
    
        final int width = getWidth();  
        if(width != 0) return getX() / getWidth();  
        else return getX();  
    

    public void setXFraction(float xFraction) 
        final int width = getWidth();  
        setX((width > 0) ? (xFraction * width) : -9999);  
    

    public float getYFraction()
    
        final int height = getHeight();  
        if(height != 0) return getY() / getHeight(); else return getY();   
    

    public void setYFraction(float yFraction) 
        final int height = getHeight();  
        setY((height > 0) ? (yFraction * height) : -9999);  
    

并将其添加到 objectAnimator:

<!-- Move -->
    <objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="@integer/card_flip_time_full"
        android:interpolator="@android:anim/linear_interpolator"
        android:propertyName="xFraction"
        android:valueFrom="-1"
        android:valueTo="0" />

这样效果更好,但是旋转轴位于 ​​FrameLayout 的中间,不会产生立方体的错觉……是否可以将旋转轴设置在某个点上?

【问题讨论】:

【参考方案1】:

通过在扩展的 FrameLayout 上创建我自己的方法解决了这个问题。这是扩展 FrameLayout 的代码:

//Rotate from Left to Right turning visible
    public float getRotateLeftRightIn()
        return getRotationY();
    
    public void setRotateLeftRightIn(int rotateLeftRightIn)
        setPivotX(getWidth());
        setPivotY(getHeight()/2);
        setRotationY(rotateLeftRightIn);
    

在 XML 上:

<!-- Rotate. -->
<objectAnimator
    android:duration="@integer/card_flip_time_full"
    android:interpolator="@android:interpolator/accelerate_decelerate"
    android:propertyName="rotateLeftRightIn"
    android:valueFrom="@integer/card_flip_rotation_off"
    android:valueTo="0" 
    android:valueType="intType"/>

在本例中,@integer/card_flip_time_full 代表整个动画的持续时间,@integer/card_flip_rotation_off 代表度数(在本例中为 -90%)。

在此之后,我需要做的就是让这个动画工作,在启动片段时,在自定义动画中设置 xml 文件

transaction.setCustomAnimations(enter,exit,popEnter,popExit);

希望这对某些人有用^^

【讨论】:

在我的情况下,我必须在片段的根视图而不是 FrameLayout 上使用额外的方法(getXFraction、setXFraction...),但结果是一样的。谢谢 @codeskraps 你能展示一下你是如何在片段的根视图上添加额外的方法的吗?我想滑动一个片段,我正在使用扩展的 FrameLayout 来做到这一点。它有效,但有一些问题。我正在寻找更好的方法来做到这一点。【参考方案2】:

除了接受的答案之外,您可以定义一个动画器集,如下所示:

  <item android:state_pressed="true">
    <set>
      <objectAnimator android:propertyName="translationZ"
        android:duration="100"
        android:valueTo="2"
        android:valueType="floatType"/>
        <!-- you could have other objectAnimator elements
             here for "x" and "y", or other properties -->
    </set>   
  </item>   

  <item android:state_enabled="true"
    android:state_pressed="false"
    android:state_focused="true">
    <set>
      <objectAnimator android:propertyName="translationZ"
        android:duration="100"
        android:valueTo="2"
        android:valueType="floatType"/>
    </set> 
  </item> 

How to use StateListAnimator?

【讨论】:

以上是关于Android - 在同一个 XML 文件上制作翻译和 objectAnimator的主要内容,如果未能解决你的问题,请参考以下文章

如何制作Android自定义键盘?

xamarin android开发 怎么实现左,右滑动翻页的效果的

Android用悬浮按钮实现翻页效果

使用 XML 定义制作三角形?

可翻转移到的自定义卡片

可翻转移到的自定义卡片