프래그먼트 간 전환 애니메이션


284

조각 사이의 전환을 애니메이션하려고합니다. 다음 Android Fragments 및 애니메이션 에서 답변을 받았습니다.

FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);

DetailsFragment newFragment = DetailsFragment.newInstance();

ft.replace(R.id.details_fragment_container, newFragment, "detailFragment");

// Start the animated transition.
ft.commit();

그리고 내 R.anim.slide_in_left

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
        <translate android:fromXDelta="50%p" android:toXDelta="0"
            android:duration="@android:integer/config_mediumAnimTime"/>
       <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
            android:duration="@android:integer/config_mediumAnimTime" />
</set>

그러나 이것을 시도했을 때 그것은 보여주었습니다.

02-08 16:27:37.961: ERROR/AndroidRuntime(1717): FATAL EXCEPTION: main
02-08 16:27:37.961: ERROR/AndroidRuntime(1717): java.lang.RuntimeException: Unknown animator name: translate
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.animation.AnimatorInflater.createAnimatorFromXml(AnimatorInflater.java:129)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.animation.AnimatorInflater.createAnimatorFromXml(AnimatorInflater.java:126)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.animation.AnimatorInflater.createAnimatorFromXml(AnimatorInflater.java:93)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.animation.AnimatorInflater.loadAnimator(AnimatorInflater.java:72)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.FragmentManagerImpl.loadAnimator(FragmentManager.java:621)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:733)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:919)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.BackStackRecord.run(BackStackRecord.java:578)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1217)

어떤 아이디어? Honeycomb API 참조를 확인하면 translate거기에 있습니다. 내가 놓친 게 무엇입니까?
프래그먼트 간 전환에 애니메이션을 적용 할 수있는 다른 방법이 있습니까? 감사합니다


애니메이션이 아닌 애니메이터를 사용하십시오! android.R.ANIMATOR.fade_in 사용, android.R.ANIM.fade_in 사용하지 마십시오-동작 버그가 있습니다
user1269737

답변:


347

당신은 새로운 사용해야 android.animation와 프레임 워크 (객체 애니메이터) FragmentTransaction.setCustomAnimations뿐만 아니라 FragmentTransaction.setTransition.

다음 setCustomAnimations은 ApiDemos의 FragmentHideShow.java 를 사용하는 예입니다 .

ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);

다음은 res / animator / fade_in.xml 의 관련 애니메이터 XML입니다 .

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:interpolator/accelerate_quad"
    android:valueFrom="0"
    android:valueTo="1"
    android:propertyName="alpha"
    android:duration="@android:integer/config_mediumAnimTime" />

<set>이전 애니메이션 프레임 워크에서와 마찬가지로을 사용하여 여러 애니메이터를 결합 할 수 있습니다 .


편집 : 사람들은 슬라이드 인 / 슬라이드 아웃에 대해 묻기 때문에 여기에 언급 할 것입니다.

슬라이드 인 및 슬라이드 아웃

당신은 물론 애니메이션을 적용 할 수 있습니다 translationX, translationY, x, 및 y특성을하지만, 일반적으로 슬라이드와 오프 스크린 컨텐츠를 애니메이션을 포함한다. 내가 아는 한 상대 값을 사용하는 전환 속성이 ​​없습니다. 그러나 이것이 직접 작성하는 것을 방해하지는 않습니다. (가) (이 경우보기에) 당신에게있는 거 생기를 객체에 그냥 할 수 있도록 해당 속성 애니메이션 단순히 getter와 setter 메소드를 필요로 기억 자신의 생성 getXFractionsetXFraction같은,보기 서브 클래스에 방법 :

public class MyFrameLayout extends FrameLayout {
    ...
    public float getXFraction() {
        return getX() / getWidth(); // TODO: guard divide-by-zero
    }

    public void setXFraction(float xFraction) {
        // TODO: cache width
        final int width = getWidth();
        setX((width > 0) ? (xFraction * width) : -9999);
    }
    ...
}

이제 다음과 같이 'xFraction'속성에 애니메이션을 적용 할 수 있습니다.

res / animator / slide_in.xml :

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

애니메이션을 적용하는 객체의 너비가 부모와 동일한 너비가 아닌 경우 상황이 제대로 표시되지 않으므로 사용 사례에 맞게 속성 구현을 조정해야 할 수도 있습니다.


8
fade_in과 fade_out이 작동하지만 / res / animator의 다른 사람들은 오류를 발생시킵니다. 그리고 그 중 어느 것도 미끄러지거나 미끄러지는 것으로 보이지 않습니다. 나는 이것을하기 위해 내 자신의 XML을 작성하려고 노력했지만 결국 모든 것은 조각 위에있는 조각입니다. 좀 더 도와주세요?
Dave MacLean

그리고 번역은 어떻습니까? XML로 정의 된 objectAnimator에서 백분율 값으로 변환하는 방법은 무엇입니까? XML로 정의 된 수직 슬라이드 애니메이션으로 뒤집는 동안 애니메이션 AdapterViewFlipper에서 성공하지 못했습니다 ...
GBouerat

6
11-19 10 : 27 : 50.912 : W / PropertyValuesHolder (23107) : float 유형의 setXFraction () 메소드가 대상 클래스 class android.widget.FrameLayout에 없습니다. 그러나 내 XML에는 사용자 정의보기 MyFrameLayout이 있습니다. 어떤 아이디어?
barkside 10

13
사실, 로마는 조언도 다른 길을 가야한다 : 지원 라이브러리를 사용하는 경우, 당신은 이전 애니메이션 FragmentTransaction.setCustomAnimations AO와 프레임 워크 (android.R.anim)를 사용합니다
pjv

1
@RomanNurik이 답변은 대부분의 장치에서 훌륭하게 작동했지만 일부 사용자 (특히 일부 Samsung Galaxy S3 / 4 전화)의 경우 어떤 이유로 애니메이션 중에 너비 가보고되지 않아 조각이 나타나지 않습니다. 여기에 표시된 것처럼 OnPredrawListener를 사용하는 사용자를 위해 작동시킬 수있었습니다. mavyasoni9891.blogspot.com/2014/06/…
ajpolt

188

나는 이렇게했다 :

방법 을 추가 하여 조각애니메이션 으로 대체하십시오 .

public void replaceFragmentWithAnimation(android.support.v4.app.Fragment fragment, String tag){
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.setCustomAnimations(R.anim.enter_from_left, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_left);
    transaction.replace(R.id.fragment_container, fragment);
    transaction.addToBackStack(tag);
    transaction.commit();
}

당신은해야 할 추가 네 애니메이션ANIM 입니다 폴더 동료자원 :

enter_from_left.xml :

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:fromXDelta="-100%" android:toXDelta="0%"
        android:fromYDelta="0%" android:toYDelta="0%"
        android:duration="700"/>
</set>

exit_to_right.xml :

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:fromXDelta="0%" android:toXDelta="100%"
        android:fromYDelta="0%" android:toYDelta="0%"
        android:duration="700" />
</set>

enter_from_right.xml :

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:fromXDelta="100%" android:toXDelta="0%"
        android:fromYDelta="0%" android:toYDelta="0%"
        android:duration="700" />
</set>

exit_to_left.xml :

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:fromXDelta="0%" android:toXDelta="-100%"
        android:fromYDelta="0%" android:toYDelta="0%"
        android:duration="700"/>
</set>

산출:

여기에 이미지 설명을 입력하십시오

그것의 완료 .


14
훌륭한 솔루션. 그러나 왜 방향을 RTL로 바꿨는지 잘 모르겠습니다. 내 방법 :.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right)
zed

2
멋진 해결책. 유사한 접근 방식과 동일한 애니메이션 파일이 활동 간 전환에 사용됩니다.
Stan

1
@MikeZriel, res-> anim-> XML을 여기에 넣으십시오
Hiren Patel

3
고마워 Hiren, 나는 iOS와 같은 속도 (700)를 (300)으로 훨씬 더 좋아지고 더 좋아집니다
Mike Zriel

3
LOL, 나는 해결책으로 돌아왔다. 각 Java 클래스에서 android.app.fragment 및 FragmentManager를 가져 왔습니다. 일부 자료를 확인한 후 'setCustomAnimations ()'을 사용하려면 가져 오기 위해 android.support.v4 라이브러리가 필요하다는 것을 알았습니다. 'support.v4.app'이어야합니다! 모든 메소드 'getFragmentManager ()'를 'getSupportFragmentManager ()'로 바꾸고 모든 가져 오기 'android.app.Fragment / FragmentManager ...'를 'android.support.v4.app ....'로 바꾼 다음이 애니메이션이 충돌없이 잘 작동하기 시작했습니다 ... 비슷한 경우에 갇힌 경우 내 솔루션을 읽으십시오. Thx Hiren Patel xD
KoreanXcodeWorker

58

Lollipop 이상에 자신을 묶을 여유가 있다면 트릭을 수행하는 것 같습니다.

import android.transition.Slide;
import android.util.Log;
import android.view.Gravity;
.
.
.
f = new MyFragment();
f.setEnterTransition(new Slide(Gravity.RIGHT));
f.setExitTransition(new Slide(Gravity.LEFT));
getFragmentManager()
    .beginTransaction()
    .replace(R.id.content, f, FRAG_TAG)  // FRAG_TAG is the tag for your fragment
    .commit();

도움이 되었기를 바랍니다.


1
Lollipop에서 달성 할 수는 있지만 Lollipop을 실행하는 장치의 비율이 무시할 수 있기 때문에 (실제로 Android 장치의 1.6 %가 Lollipop을 실행하고 있기 때문에) 실용적이지 않습니다.
Eran Goldin

1
new Slide(...): 호출 API 레벨 21를 필요
들은 Chintan SONI

getKey ()는 무엇을 의미합니까?
Alvaro

13
@EranGoldin 영원히 지속되는 것은 없습니다. 오늘 Android 2.0+ 전용 솔루션을 원하십니까?
Tom

@Tom 포인트가 있습니다. 그러나 앱에 사용자 기반이 큰 경우 API 수준을 높일 수는 없습니다. 대부분의 사용자가 더 이상 앱을 실행할 수 없다면 전혀 해결책이 아닙니다.
Eran Goldin

47

Nurik 의 대답은 매우 도움이되었다,하지만 난 찾을 때까지 나는 일에 그것을 얻을 수없는 . 즉, 호환성 라이브러리 (예 : FragmentManager 대신 SupportFragmentManager)를 사용하는 경우 XML 애니메이션 파일의 구문이 다릅니다.


28

다음은 프래그먼트 간 슬라이드 인 / 아웃 애니메이션입니다.

FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.setCustomAnimations(R.animator.enter_anim, R.animator.exit_anim);
transaction.replace(R.id.listFragment, new YourFragment());
transaction.commit();

우리는 objectAnimator를 사용하고 있습니다.

다음은 애니메이터 하위 폴더 에있는 두 개의 xml 파일입니다 .

enter_anim.xml

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

exit_anim.xml

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

나는 그것이 누군가를 도울 수 있기를 바랍니다.


37
2000px로 뷰를 옮기는 것은 매우 추악한 해결책입니다.
carlo.marinangeli 2019

4
exit_anim은 화면에서 "팝"되어 화면에서 다시 애니메이션되지 않습니다. 어떤 아이디어? 나는 사용하고있다.setCustomAnimations(R.animator.slide_in_left, R.animator.slide_out_right, R.animator.slide_in_left, R.animator.slide_out_right)
Mr Pablo

@ MrPablo, 그 이유는 아마도 위의 코드를 붙여 넣지 않은 것입니다. setCustomAnimations는 replace 메소드 전에 호출해야합니다.
Galya

이 경우 다른 조각을 애니메이션으로 바꾸고 애니메이션 시간 초과 또는 지속 시간 직전과 응용 프로그램으로 다시 돌아 오기 직전에 앱을 최소화하면 이전 조각과 현재 조각이 병렬로 표시됩니다.
Prince

23

잡힌 다른 사람은 트랜잭션을 빌드 할 때 바꾸거나 추가하기 전에 setCustomAnimations가 호출되는지 확인하십시오.


12

FragmentTransaction의 Android SDK 구현은 Animator지원 라이브러리가 원하는 동안 원합니다. Animation왜 그런지 묻지 않지만 strangeluk의 의견 후에 android 4.0.3 코드 및 지원 라이브러리를 살펴 보았습니다. Android SDK 사용 loadAnimator()및 지원 라이브러리 사용loadAnimation()


7

이 간단하고 빠른 솔루션을 사용해보십시오. 안드로이드는 몇 가지 기본 기능을 제공합니다 animation.

fragmentTransaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
fragmentManager.addOnBackStackChangedListener(this);
fragmentTransaction.replace(R.id.frame, firstFragment, "h");
fragmentTransaction.addToBackStack("h");
fragmentTransaction.commit();

산출:

여기에 이미지 설명을 입력하십시오


와우 .. 이것은 정답입니다! 간단하고 우아한 솔루션. 다른 제안에 비해 매우 매끄 럽습니다
Chathura Buddhika
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.