Подтвердить что ты не робот

Android: использование ObjectAnimator для преобразования представления с дробными значениями параметра View

Похоже, что старые анимации просмотра (translate, scale и т.д.) больше не принимаются AnimationInflater, по крайней мере, с ICS. Я прочитал его код в 4.0.4, и он явно ожидает только элементы XML set, objectAnimator, animator.

Несмотря на то, что документация на http://developer.android.com/guide/topics/resources/animation-resource.html продолжает включать анимацию вида, они выглядят устаревшими. Попытка использовать их приводит, например, к ошибке java.lang.RuntimeException: Unknown animator name: translate.

Таким образом, становится необходимо использовать Android objectAnimator. Тем не менее, он не принимает дробные значения связанного измерения самого себя или своего родителя (например, ширина для translationX), поскольку старые анимации вида выполнялись в форме "75%p".

Построение objectAnimator вручную во время выполнения, путем программной выборки Фрагмента, нецелесообразно, поскольку FragmentTransaction принимает только декларативные анимации, заданные остатком.

Моя цель состоит в том, чтобы перевести на экран Фрагмент, заполняющий всю активность (я в основном делаю переход смены между двумя фрагментами). Это существующая реализация 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.

Спасибо!

4b9b3361

Ответ 1

Фактически объектные аниматоры принимают дробные значения. Но, возможно, вы не поняли базовую концепцию objectAnimator или, в более общем смысле, аниматора ценности. Аниматор значений будет анимировать значение, относящееся к свойству (например, цвет, положение на экране (X, Y), альфа-параметр или все, что вы хотите). Чтобы создать такое свойство (в вашем случае xFraction и yFraction), вам нужно создать собственные геттеры и сеттеры, связанные с этим именем свойства. Допустим, вы хотите перевести FrameLayout с 0% до 25% от размера всего экрана. Затем вам нужно создать пользовательский вид, который обертывает объекты FrameLayout и записывает ваши получатели и сеттеры.

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 и раздувая его с помощью 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);

Надеюсь, это поможет вам!

Оливье,

Ответ 2

Android SDK для реализации FragmentTransaction ожидает Animator, хотя по какой-то неясной причине реализация библиотеки поддержки ожидает Animation, если вы используете реализацию Fragment из библиотеки поддержки, ваша анимация перевода будет работать

Ответ 3

Вот важный вопрос для тех, кто пытается создать анимацию вида, например translate и scale.

Анимации свойств расположены в каталоге с именем "аниматор": res/animator/filename.xml

НО, просмотр анимаций должен быть помещен в каталог, просто называемый "anim": res/anim/filename.xml

Сначала я поместил анимацию в анимационную папку и был смущен тем, что Android Studio жалуется, что перевод не является допустимым элементом. Таким образом, НЕТ, просмотр анимации не устарел. У них просто есть свое место для какой-то непонятной причины.

Ответ 4

вот полный рабочий пример (работы, описанные автором принятого ответа.)

Нажатие кнопки переключает между двумя фрагментами A и B (с помощью слайд-анимации справа налево). Фрагменты - это просто глупый текст (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>

Ответ 5

Просмотр анимаций не устаревает. Если вы используете Eclipse, вы можете найти их под анимацией анимации в качестве типа ресурса при создании нового файла Android XML.