ทำให้เกิดการเปลี่ยนแปลงระหว่างชิ้นส่วนต่างๆ


284

ฉันกำลังพยายามทำให้การเปลี่ยนแปลงระหว่างชิ้นส่วนต่างๆ ฉันได้รับคำตอบจากชิ้นส่วนและภาพเคลื่อนไหว Androidต่อไปนี้

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อยู่ที่นั่น ฉันพลาดอะไร?
มีวิธีอื่นอีกไหมในการทำให้การเปลี่ยนแปลงระหว่างชิ้นส่วนต่างๆ ขอบคุณ


ใช้ ANIMATOR --- ไม่ใช่ภาพเคลื่อนไหว! ใช้ android.R.ANIMATOR.fade_in ใช้งานไม่ต้องใช้ android.R.ANIM.fade_in - มันมีพฤติกรรม BUGS
user1269737

คำตอบ:


347

คุณจำเป็นต้องใช้ใหม่android.animationกรอบ (แอนิเมชั่วัตถุ) ด้วยเช่นเดียวกับFragmentTransaction.setCustomAnimationsFragmentTransaction.setTransition

นี่คือตัวอย่างการใช้งานsetCustomAnimationsจากFragmentHideShow.javaของ ApiDemos :

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

และนี่คือ XML แอนิเมเตอร์ที่เกี่ยวข้องจากres / animator / fade_in.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

แล้วการแปลล่ะ? คุณแปลด้วยค่าเป็นเปอร์เซ็นต์ใน objectAnimator ที่กำหนดใน XML ได้อย่างไร ฉันไม่ประสบความสำเร็จในการเคลื่อนไหว AdapterViewFlipper ระหว่างการพลิกด้วยภาพเคลื่อนไหวสไลด์แนวตั้งที่กำหนดใน xml ...
GBouerat

6
ฉันได้รับ 11-19 10: 27: 50.912: W / PropertyValuesHolder (23107): วิธี setXFraction () ด้วยการลอยประเภทไม่พบในชั้นเป้าหมายเป้าหมาย android.widget.FrameLayout แต่ใน XML ของฉันฉันมีมุมมองที่กำหนดเองของฉัน MyFrameLayout ความคิดใด ๆ
barkside

13
ที่จริงแล้วโรมันคำแนะนำควรไปในทางอื่นเช่นกัน: เมื่อใช้ห้องสมุดสนับสนุนคุณต้องใช้เฟรมเวิร์กแอนิเมชั่นเก่า (android.R.anim) กับ FragmentTransaction.setCustomAnimations ao
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
ทางออกที่ดีเลิศ วิธีการที่คล้ายกันและไฟล์ภาพเคลื่อนไหวเดียวกันทำงานสำหรับการเปลี่ยนระหว่างกิจกรรม
สแตน

1
@MikeZriel, res -> anim -> ใส่ xml ของคุณที่นี่
Hiren Patel

3
ขอบคุณ Hiren ฉันเปลี่ยนความเร็ว (700) เป็น (300) ดีขึ้นและมากขึ้นเช่น iOS
Mike Zriel

3
ฮ่า ๆ ฉันกลับมาพร้อมทางออก ฉันกำลังนำเข้า android.app.fragment และ FragmentManager ในแต่ละคลาส java หลังจากตรวจสอบวัสดุบางอย่างแล้วฉันพบว่าการใช้ 'setCustomAnimations ()' จำเป็นต้องมีการนำเข้าไลบรารี android.support.v4 สิ่งสำคัญที่จะบอกว่าควรจะเป็น 'support.v4.app'! ฉันแทนที่ 'getFragmentManager ()' ด้วยเมธอด 'getSupportFragmentManager ()' และนำเข้าทั้งหมด 'android.app.Fragment / FragmentManager ... ' เป็น 'android.support.v4.app .... ' จากนั้น แอนิเมชั่นเริ่มทำงานได้ดีโดยไม่มีข้อผิดพลาด ... ถ้าพวกคุณติดอยู่ในกรณีที่คล้ายกันอ่านวิธีแก้ปัญหาของฉัน ขอบคุณ 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 นั้นมีน้อยมาก (ปัจจุบัน 1.6% ของอุปกรณ์ Android ที่ใช้ Lollipop)
Eran Goldin

1
new Slide(...): การโทรต้องใช้ API ระดับ 21
Chintan Soni

getKey () หมายถึงอะไร
Alvaro

13
@EranGoldin ไม่มีสิ่งใดจะคงอยู่ตลอดไป .. คุณจะเย้ยหยันในโซลูชั่น Android 2.0+ เพียงวันนี้หรือไม่?
Tom

@ Tom คุณมีจุด อย่างไรก็ตามเมื่อแอปของคุณมีฐานผู้ใช้จำนวนมากคุณจะไม่สามารถชนกับระดับ API ได้ หากผู้ใช้ส่วนใหญ่ของคุณจะไม่สามารถเรียกใช้แอปของคุณได้อีกต่อไปนั่นก็ไม่ใช่วิธีแก้ปัญหาเลย
Eran Goldin

47

Nurikคำตอบ 's เป็นประโยชน์มาก แต่ฉันไม่สามารถรับมันในการทำงานจนกว่าฉันพบนี้ กล่าวโดยย่อหากคุณใช้ไลบรารีความเข้ากันได้ (เช่น SupportFragmentManager แทน FragmentManager) ไวยากรณ์ของไฟล์ภาพเคลื่อนไหว 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 สองไฟล์ในโฟลเดอร์ย่อยAnimator

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
การย้ายมุมมองสำหรับ 2000 px เป็นวิธีแก้ปัญหาที่น่าเกลียดมาก
carlo.marinangeli

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 ก่อนวิธีการแทนที่
Galya

ในกรณีนี้ถ้าฉันแทนที่แฟรกเมนต์อื่นด้วยแอนิเมชันและฉันจะย่อขนาดแอพทันทีก่อนที่การหมดเวลาของภาพเคลื่อนไหวหรือระยะเวลาที่มากกว่านั้นกลับมาที่แอปพลิเคชันอีกครั้งมันจะแสดงแฟรกเมนต์ก่อนหน้า
เจ้าชาย

23

สำหรับใครก็ตามที่ถูกจับได้ให้ตรวจสอบให้แน่ใจว่ามีการเรียกใช้ setCustomAnimations ก่อนการเรียกเพื่อแทนที่ / เพิ่มเมื่อสร้างธุรกรรม


12

การใช้งาน SDK ของ FragmentTransaction ต้องการการAnimatorสนับสนุนในขณะที่ห้องสมุดAnimationไม่ต้องถามฉันทำไม แต่หลังจากความคิดเห็นของ strangeluk ฉันมองเข้าไปใน Android 4.0.3 รหัสและห้องสมุดสนับสนุน Android SDK ใช้loadAnimator()และใช้ไลบรารีสนับสนุนloadAnimation()


7

ลองใช้วิธีแก้ปัญหาที่ง่ายและรวดเร็วนี้ Android ให้เริ่มต้นบางanimations

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.