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


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 메소드를 필요로 기억 자신의 생성 getXFraction 과 setXFraction같은,보기 서브 클래스에 방법 :

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.