ชิ้นส่วน Android และภาพเคลื่อนไหว


265

คุณควรใช้การเลื่อนแบบนั้นเช่นไคลเอ็นต์ Honeycomb Gmail ใช้อย่างไร

สามารถTransactionManagerจัดการสิ่งนี้โดยอัตโนมัติโดยการเพิ่มและลบ Fragments มันยากที่จะทดสอบสิ่งนี้เนื่องจากตัวจำลองเป็นสไลด์โชว์ :)

คำตอบ:


388

ในการเคลื่อนไหวการเปลี่ยนระหว่างแฟรกเมนต์หรือเพื่อทำให้กระบวนการแสดงหรือซ่อนแฟรกเมนต์ที่คุณใช้Fragment Managerเพื่อสร้างFragment Transactionในการสร้าง

ภายในแต่ละ Fragment Transaction คุณสามารถระบุภาพเคลื่อนไหวเข้าและออกที่จะใช้สำหรับการแสดงและซ่อนตามลำดับ (หรือทั้งสองอย่างเมื่อใช้การแทนที่)

รหัสต่อไปนี้แสดงให้เห็นว่าคุณจะแทนที่ชิ้นส่วนได้อย่างไรโดยการเลื่อนชิ้นส่วนหนึ่งออกมาและเลื่อนส่วนอื่น ๆ เข้ามาแทน

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();

เพื่อให้บรรลุสิ่งเดียวกันด้วยการซ่อนหรือแสดงชิ้นส่วนที่คุณเพียงโทรft.showหรือft.hideผ่านในส่วนที่คุณต้องการแสดงหรือซ่อนตามลำดับ

สำหรับการอ้างอิงนิยามของภาพเคลื่อนไหว XML จะใช้objectAnimatorแท็ก ตัวอย่างของ slide_in_left อาจมีลักษณะเช่นนี้:

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

57
เมื่อฉันพยายามนี้มันแสดงRuntimeException: ชื่อภาพเคลื่อนไหวที่ไม่รู้จัก: แปล
Labeeb Panampullan

3
ตรวจสอบให้แน่ใจว่าภาพเคลื่อนไหวที่กำหนดใน slide_in_left และด้านขวาถูกสร้างขึ้นโดยใช้ชุดคำจำกัดความของ objectAnimator แทนที่จะเป็นคำจำกัดความภาพเคลื่อนไหวเก่า
Reto Meier

7
นั่นช่วยได้มาก ฉันอยู่ในเส้นทางที่ถูกต้อง แต่ไม่ได้ไปถึงที่นั่น สำหรับผู้อ่านคนอื่นคุณอาจมี android: interpolator เป็นคุณลักษณะโดยระบุสิ่งที่คุณชื่นชอบ (เช่น "@android: interpolator / linear") มันเริ่มต้นที่ "@android: interpolator / acceler_decelerate"
Dave MacLean

6
ฉันกำลังกำหนดเป้าหมาย API ระดับ 7 ด้วย API ความเข้ากันได้ มีวิธีสำหรับฉันที่จะทำให้ชิ้นส่วนเคลื่อนไหวหรือไม่?
Jarrod Smith

5
@JarrodSmith คุณสามารถลองใช้ไลบรารีความเข้ากันได้เช่นNineOldAndroidsเพื่อนำ Honeycomb API ลงไปที่ Eclair
นายเอส

249

หากคุณไม่จำเป็นต้องใช้ไลบรารีการสนับสนุนโปรดดูคำตอบของโรมัน

แต่ถ้าคุณต้องการใช้ไลบรารีการสนับสนุนคุณต้องใช้กรอบแอนิเมชั่นเก่าตามที่อธิบายไว้ด้านล่าง

หลังจากปรึกษาคำตอบของ Retoและblindstuffฉันได้รับรหัสต่อไปนี้ที่ใช้งานได้

ชิ้นส่วนที่ปรากฏจะเลื่อนจากด้านขวาและเลื่อนไปทางซ้ายเมื่อกดด้านหลัง

FragmentManager fragmentManager = getSupportFragmentManager();

FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.setCustomAnimations(R.anim.enter, R.anim.exit, R.anim.pop_enter, R.anim.pop_exit);

CustomFragment newCustomFragment = CustomFragment.newInstance();
transaction.replace(R.id.fragment_container, newCustomFragment );
transaction.addToBackStack(null);
transaction.commit();

คำสั่งซื้อเป็นสิ่งสำคัญ หมายความว่าคุณต้องโทรหาsetCustomAnimations()ก่อนมิreplace()ฉะนั้นการเคลื่อนไหวจะไม่มีผล!

ถัดไปไฟล์เหล่านี้จะต้องอยู่ในres / animโฟลเดอร์

enter.xml :

<?xml version="1.0" encoding="utf-8"?>
<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="100%"
               android:toXDelta="0"
               android:interpolator="@android:anim/decelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

exit.xml :

<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="0"
               android:toXDelta="-100%"
               android:interpolator="@android:anim/accelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

pop_enter.xml :

<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="-100%"
               android:toXDelta="0"
               android:interpolator="@android:anim/decelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

pop_exit.xml :

<?xml version="1.0" encoding="utf-8"?>
<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="0"
               android:toXDelta="100%"
               android:interpolator="@android:anim/accelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

ระยะเวลาของภาพเคลื่อนไหวสามารถเปลี่ยนเป็นค่าเริ่มต้นเช่น@android:integer/config_shortAnimTimeหรือหมายเลขอื่น ๆ

โปรดทราบว่าหากในระหว่างการเปลี่ยนชิ้นส่วนการเปลี่ยนแปลงการกำหนดค่าที่เกิดขึ้น (เช่นการหมุน) การกระทำกลับไม่เคลื่อนไหว นี่เป็นข้อบกพร่องที่ทำเป็นเอกสารซึ่งยังคงมีอยู่ใน rev 20 ของไลบรารีการสนับสนุน


47
นี่เพิ่งช่วยฉัน หมายเหตุให้ความสนใจกับการสั่งซื้อเป็นสิ่งสำคัญซึ่งเป็นธรรมชาติฉันพลาดครั้งแรก หมายความว่าคุณต้องเรียกใช้ setCustomAnimations () ก่อนแทนที่ ()
Stephen Kidson

3
ฉันพยายามที่จะใช้กับชิ้นส่วนของฉันฉันเขียนทุกอย่างที่คุณพูดถึง แต่ logcat พูดว่า: ไม่ทราบชื่อแอนิเมเตอร์แปลฉันจะเอาชนะปัญหานี้ได้อย่างไร โดยวิธีการที่ฉันเรียกชิ้นส่วนของฉันในการนำทางลิ้นชัก (เมนูเลื่อน)
Zafer Celaloglu

ใช้งานได้ดี แต่ปรากฎว่าการสร้างสิ่งนี้ด้วยเครื่องมือสร้าง 21.1 สร้างข้อผิดพลาดว่า "ชื่อไฟล์ไม่ถูกต้อง: ต้องมีตัวอักษรและตัวเลขที่เล็กกว่าเท่านั้น ([a-z0-9_.])" ฉันขอแนะนำให้แก้ไขชื่อไฟล์ในคำตอบของ pop_enter.xml และ pop_exit.xml
smichak

ทางออกที่ดีเยี่ยมและใช้งานได้ดีเมื่อฉันกดปุ่มย้อนกลับ ฉันมีคำถามเดียว: ถ้าฉันต้องการสร้าง backButton ที่กำหนดเองฉันควรจะเรียกใช้รหัสใดในการทำซ้ำพฤติกรรมจากปุ่มย้อนกลับ
โทมัส Teilmann

1
โทมัสถ้าคุณต้องการกลับมาคุณควรใช้แบบฟอร์มนี้: .setCustomAnimations (R.anim.pop_enter, R.anim.pop_exit, R.anim.enter, R.anim.exit)
Alex Zaraos

26

ฉันขอแนะนำให้คุณใช้สิ่งนี้แทนการสร้างไฟล์แอนิเมชันเพราะมันเป็นทางออกที่ดีกว่ามาก Android Studio มีค่าเริ่มต้นที่ animationคุณสามารถใช้ได้โดยไม่ต้องสร้างไฟล์ XML ใหม่ ชื่อภาพเคลื่อนไหวคือandroid.R.anim.slide_in_leftและandroid.R.anim.slide_out_rightและคุณสามารถใช้มันได้ดังต่อไปนี้:

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();

เอาท์พุท:

ป้อนคำอธิบายรูปภาพที่นี่


1
android.R ... "Android Studio ให้ภาพเคลื่อนไหวเริ่มต้น" นั่นไม่ใช่สำหรับ android studio มันสามารถทำงานใน eclipse ได้เช่นกัน android.R เป็น android โดยเฉพาะและวิธีที่คุณไม่ได้แชร์ข้อมูลที่ apis มีอยู่เพราะ เนื้อหาใน android.R นั้นแตกต่างกันใน apis ที่แตกต่างกัน
steve moretz

@stevemoretz thaxs bro ฉันเห็นด้วยกับประเด็นของคุณ .. ฉันจะแก้ไขและอัปเดตคำตอบของฉัน ...
Gowthaman M

5

ไลบรารีการสนับสนุนที่แก้ไขแล้วของฉันรองรับการใช้ทั้งภาพเคลื่อนไหวดู (เช่น<translate>, <rotate>) และ Object Animators (เช่น<objectAnimator>) สำหรับ Fragment Transitions มันถูกนำมาใช้กับNineOldAndroids อ้างถึงเอกสารของฉันเกี่ยวกับ GitHub สำหรับรายละเอียด


2

สำหรับฉันฉันต้องการมุมมอง diraction:

ใน -> ปัดจากขวา

ออก -> ปัดไปทางซ้าย

ที่นี่ใช้งานได้สำหรับฉันรหัส:

slide_in_right.xml

<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>

slide_out_left.xml

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

รหัสการทำธุรกรรม:

inline fun FragmentActivity.setContentFragment(
        containerViewId: Int,
        backStack: Boolean = false,
        isAnimate: Boolean = false,
        f: () -> Fragment

): Fragment? {
    val manager = supportFragmentManager
    return f().apply {
        manager.beginTransaction().let {
            if (isAnimate)
                it.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left)

            if (backStack) {
                it.replace(containerViewId, this, "Fr").addToBackStack("Fr").commit()
            } else {
                it.replace(containerViewId, this, "Fr").commit()
            }
        }
    }
}

Android ดูเหมือนจะกะพริบช่วงการเปลี่ยนภาพด้วยภาพเคลื่อนไหวเหล่านั้น (โดยเฉพาะการแปล)
Gabriel De Oliveira Rohden

@GabrielDeOliveiraRohden สำหรับฉันไม่ได้อยู่ในทุก Casses
Serg Burlaka

1

ฉันแก้ไขวิธีนี้ด้านล่าง

Animation anim = AnimationUtils.loadAnimation(this, R.anim.slide);
fg.startAnimation(anim);
this.fg.setVisibility(View.VISIBLE); //fg is a View object indicate fragment
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.