ภาพเคลื่อนไหวการทำธุรกรรมส่วนย่อย: เลื่อนเข้าและเลื่อนออก


104

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

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

แต่ฉันต้องการกลับภาพเคลื่อนไหวนี้: ส่วนเก่าเลื่อนออกไปทางซ้ายและส่วนใหม่เลื่อนไปทางขวา แต่ไม่มีค่าของ R.animดูเหมือนว่าไฟล์ที่จะเป็นประโยชน์สำหรับขอบเขตของฉัน

ฉันจะทำมันได้อย่างไร?


ในความคิดของฉันคุณสามารถลองoverride key_code==back_key_pressในส่วนที่สองของคุณ
Nitin Misra

บางทีฉันอาจจะอธิบายตัวเองไม่เก่ง ฉันต้องการให้เมื่อทำการแลกเปลี่ยนชิ้นส่วนสไลด์ส่วนเก่าทางด้านซ้ายและส่วนใหม่เข้าจากด้านขวา ด้วยรหัสนั้นพฤติกรรมจะตรงกันข้าม
giozh

1
ตอบที่นี่: stackoverflow.com/questions/10886669/…
Carsten

คำตอบ:


278

อัปเดต สำหรับ Android v19 + ดูลิงค์นี้ทาง @Sandra

คุณสามารถสร้างภาพเคลื่อนไหวของคุณเอง วางไฟล์ XML ของภาพเคลื่อนไหวในรูปแบบres > 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%p" android:toXDelta="0%"
      android:fromYDelta="0%" android:toYDelta="0%"
      android:duration="@android:integer/config_mediumAnimTime"/>
</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%p" android:toXDelta="0%"
     android:fromYDelta="0%" android:toYDelta="0%"
     android:duration="@android:integer/config_mediumAnimTime" />
</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%p"
      android:fromYDelta="0%" android:toYDelta="0%"
      android:duration="@android:integer/config_mediumAnimTime"/>
</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%p"
     android:fromYDelta="0%" android:toYDelta="0%"
     android:duration="@android:integer/config_mediumAnimTime" />
</set>

คุณสามารถเปลี่ยนระยะเวลาเป็นเวลาเคลื่อนไหวสั้น ๆ

android:duration="@android:integer/config_shortAnimTime"

หรือเวลาในการเคลื่อนไหวที่ยาวนาน

android:duration="@android:integer/config_longAnimTime" 

USAGE (โปรดทราบว่าลำดับที่คุณเรียกเมธอดในธุรกรรมมีความสำคัญเพิ่มภาพเคลื่อนไหวก่อนที่คุณจะเรียก. replace, .commit):

FragmentTransaction transaction = supportFragmentManager.beginTransaction();
transaction.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right);
transaction.replace(R.id.content_frame, fragment);
transaction.addToBackStack(null);
transaction.commit();

29
เพียงใช้ภาพเคลื่อนไหว xml เหล่านี้เมื่อแทนที่แฟรกเมนต์เช่น fragmentTransaction.setCustomAnimations (R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right); fragmentTransaction.replace (R.id.content_frame, fragDettRisorsa); fragmentTransaction.addToBackStack (null); fragmentTransaction.commit ();
moondroid

11
มันบอกชื่อแอนิเมเตอร์ที่ไม่รู้จัก: แปล
Hirak Chhatbar

9
ไม่ทำงาน ... ทำให้เกิด "java.lang.RuntimeException: Unknown animator name: translate" วิธีนี้ใช้ได้ผลสำหรับฉัน Trickyandroid.com/fragments-translate-animation
Ataru

27
ระยะเวลา700ค่อนข้างมากสำหรับภาพเคลื่อนไหวดังกล่าวในความคิดของฉัน กรอบ Android มี 3 สถานีที่ตั้งไว้สำหรับระยะเวลา: android:duration="@android:integer/config_longAnimTime", android:duration="@android:integer/config_mediumAnimTime"และandroid:duration="@android:integer/config_shortAnimTime"ซึ่งสอดคล้องกับ 500, 400 และ 200 ผมคิดว่าหน่วยเป็นมิลลิวินาที แต่ผมไม่แน่ใจว่า
Krøllebølle

6
ใช้งานได้เฉพาะเมื่อใช้ส่วนสนับสนุน (android.support.v4.app.Fragment)
Aviv Ben Shabat

37

มีสามวิธีในการทำธุรกรรมแอนิเมชันในส่วนย่อย

การเปลี่ยน

ดังนั้นจำเป็นต้องใช้หนึ่งในการเปลี่ยนในตัวใช้เมธอด setTranstion ():

getSupportFragmentManager()
        .beginTransaction()
        .setTransition( FragmentTransaction.TRANSIT_FRAGMENT_OPEN )
        .show( m_topFragment )
        .commit()

ภาพเคลื่อนไหวที่กำหนดเอง

คุณยังสามารถปรับแต่งภาพเคลื่อนไหวโดยใช้เมธอด setCustomAnimations ():

getSupportFragmentManager()
        .beginTransaction()
        .setCustomAnimations( R.anim.slide_up, 0, 0, R.anim.slide_down)
        .show( m_topFragment )
        .commit()

slide_up.xml

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:propertyName="translationY"
        android:valueType="floatType"
        android:valueFrom="1280"
        android:valueTo="0"
        android:duration="@android:integer/config_mediumAnimTime"/>

slide_down.xml

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:propertyName="translationY"
        android:valueType="floatType"
        android:valueFrom="0"
        android:valueTo="1280"
        android:duration="@android:integer/config_mediumAnimTime"/>

ภาพเคลื่อนไหวหลายภาพ

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

getSupportFragmentManager()
        .beginTransaction()
        .setCustomAnimations( R.anim.abc_slide_in_top, R.anim.abc_slide_out_top ) // Top Fragment Animation
        .show( m_topFragment )
        .setCustomAnimations( R.anim.abc_slide_in_bottom, R.anim.abc_slide_out_bottom ) // Bottom Fragment Animation
        .show( m_bottomFragment )
        .commit()

หากต้องการรายละเอียดเพิ่มเติมคุณสามารถไปที่ URL

หมายเหตุ: -คุณสามารถตรวจสอบภาพเคลื่อนไหวได้ตามความต้องการของคุณเนื่องจากข้างต้นอาจมีปัญหา


1
คุณกำลังใช้ค่าที่เข้ารหัสแบบแน่นอน ส่วนก่อนหน้านี้จะหายไปกลางหน้าจอสำหรับการแสดงผลที่มีความละเอียดสูงขึ้น
TheLibrarian

@TheLibrarianCz นี่เป็นเพียงตัวอย่าง
duggu

1
มันเป็นและไม่ใช่
TheLibrarian

ขึ้นอยู่กับว่าบางคนต้องการให้ช้อนป้อนอาหารจากตัวอย่างด้านบนหรือเรียนรู้สิ่งที่พวกเขาสามารถทำได้ด้วยตัวอย่าง
duggu

สิ่งที่อยู่ในตัวแปร m_topFragment
เจ้าชาย

6

ฉันมีปัญหาเดียวกันฉันใช้วิธีง่ายๆ

1) สร้าง scroll_out_right.xml ในโฟลเดอร์ anim

  <?xml version="1.0" encoding="utf-8"?>
    <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>

2) สร้าง scroll_in_left.xml ในโฟลเดอร์ anim

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

3) เพียงแค่ใช้การทำธุรกรรมส่วน setCustomeAnimations () กับ xml ที่กำหนดเองสองตัวและ xml เริ่มต้นสองรายการสำหรับภาพเคลื่อนไหวดังนี้: -

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

5

slide_in_down.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="@android:integer/config_longAnimTime"
        android:fromYDelta="0%p"
        android:toYDelta="100%p" />
</set>

slide_in_up.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="@android:integer/config_longAnimTime"
        android:fromYDelta="100%p"
        android:toYDelta="0%p" />
</set>

slide_out_down.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="@android:integer/config_longAnimTime"
        android:fromYDelta="-100%"
        android:toYDelta="0"
        />
</set>

slide_out_up.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="@android:integer/config_longAnimTime"
        android:fromYDelta="0%p"
        android:toYDelta="-100%p"
        />
</set>

ทิศทาง = ลง

            activity.getSupportFragmentManager()
                    .beginTransaction()
                    .setCustomAnimations(R.anim.slide_out_down, R.anim.slide_in_down)
                    .replace(R.id.container, new CardFrontFragment())
                    .commit();

ทิศทาง = ขึ้น

           activity.getSupportFragmentManager()
                    .beginTransaction()
                    .setCustomAnimations(R.anim.slide_in_up, R.anim.slide_out_up)
                    .replace(R.id.container, new CardFrontFragment())
                    .commit();

2

นี่เป็นอีกวิธีหนึ่งที่ฉันใช้:

public class CustomAnimator {
    private static final String TAG = "com.example.CustomAnimator";

    private static Stack<AnimationEntry> animation_stack    = new Stack<>();

    public static final int                 DIRECTION_LEFT  = 1;
    public static final int                 DIRECTION_RIGHT = -1;
    public static final int                 DIRECTION_UP    = 2;
    public static final int                 DIRECTION_DOWN  = -2;

    static class AnimationEntry {
        View in;
        View    out;
        int     direction;
        long    duration;
    }

    public static boolean hasHistory() {
        return !animation_stack.empty();
    }

    public static void reversePrevious() {
        if (!animation_stack.empty()) {
            AnimationEntry entry = animation_stack.pop();
            slide(entry.out, entry.in, -entry.direction, entry.duration, false);
        }
    }

    public static void clearHistory() {
        animation_stack.clear();
    }

    public static void slide(final View in, View out, final int direction, long duration) {
        slide(in, out, direction, duration, true);
    }

    private static void slide(final View in, final View out, final int direction, final long duration, final boolean save) {

        ViewGroup in_parent = (ViewGroup) in.getParent();
        ViewGroup out_parent = (ViewGroup) out.getParent();

        if (!in_parent.equals(out_parent)) {
            return;
        }

        int parent_width = in_parent.getWidth();
        int parent_height = in_parent.getHeight();

        ObjectAnimator slide_out;
        ObjectAnimator slide_in;

        switch (direction) {
            case DIRECTION_LEFT:
            default:
                slide_in = ObjectAnimator.ofFloat(in, "translationX", parent_width, 0);
                slide_out = ObjectAnimator.ofFloat(out, "translationX", 0, -out.getWidth());
                break;
            case DIRECTION_RIGHT:
                slide_in = ObjectAnimator.ofFloat(in, "translationX", -out.getWidth(), 0);
                slide_out = ObjectAnimator.ofFloat(out, "translationX", 0, parent_width);
                break;
            case DIRECTION_UP:
                slide_in = ObjectAnimator.ofFloat(in, "translationY", parent_height, 0);
                slide_out = ObjectAnimator.ofFloat(out, "translationY", 0, -out.getHeight());
                break;
            case DIRECTION_DOWN:
                slide_in = ObjectAnimator.ofFloat(in, "translationY", -out.getHeight(), 0);
                slide_out = ObjectAnimator.ofFloat(out, "translationY", 0, parent_height);
                break;
        }

        AnimatorSet animations = new AnimatorSet();
        animations.setDuration(duration);
        animations.playTogether(slide_in, slide_out);
        animations.addListener(new Animator.AnimatorListener() {

            @Override
            public void onAnimationCancel(Animator arg0) {
            }

            @Override
            public void onAnimationEnd(Animator arg0) {
                out.setVisibility(View.INVISIBLE);
                if (save) {
                    AnimationEntry ae = new AnimationEntry();
                    ae.in = in;
                    ae.out = out;
                    ae.direction = direction;
                    ae.duration = duration;
                    animation_stack.push(ae);
                }
            }

            @Override
            public void onAnimationRepeat(Animator arg0) {
            }

            @Override
            public void onAnimationStart(Animator arg0) {
                in.setVisibility(View.VISIBLE);
            }
        });
        animations.start();
    }
}

การใช้คลาส สมมติว่าคุณมีชิ้นส่วนสองชิ้น (รายการและชิ้นส่วนรายละเอียด) ดังที่แสดงด้านล่าง

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ui_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <FrameLayout
        android:id="@+id/list_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <FrameLayout
        android:id="@+id/details_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone" />
</FrameLayout>

การใช้งาน

View details_container = findViewById(R.id.details_container);
View list_container = findViewById(R.id.list_container);
// You can select the direction left/right/up/down and the duration
CustomAnimator.slide(list_container, details_container,CustomAnimator.DIRECTION_LEFT, 400);

คุณสามารถใช้ฟังก์ชันCustomAnimator.reversePrevious();เพื่อรับมุมมองก่อนหน้าเมื่อผู้ใช้กดย้อนกลับ


1
แน่ใจหรือว่าใช้ Fragments ของ Android =) ดูเหมือนว่าจะใช้ระบบดูตามการจัดการส่วนที่กำหนดเอง)
จูบ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.