Hoạt ảnh giao dịch phân mảnh: trượt vào và trượt ra


104

Tôi đã kiểm tra một số hướng dẫn để tạo hoạt ảnh giao dịch giữa các đoạn. Tôi đã sử dụng phương pháp này cho hoạt ảnh và nó hoạt động:

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

Nhưng tôi muốn đảo ngược hoạt ảnh này: phân đoạn cũ trượt ra bên trái và phân đoạn mới trượt sang bên phải, nhưng không có giá trị nào của R.animtệp dường như hữu ích cho phạm vi của tôi.

Tôi làm nó như thế nào?


theo ý kiến ​​của tôi, bạn có thể thử override key_code==back_key_presstrong phân đoạn thứ hai của bạn.
Nitin Misra

có lẽ tôi không giải thích được bản thân mình tốt. Tôi muốn rằng khi hoán đổi phân đoạn, phân đoạn cũ trượt ở phía bên trái và phân đoạn mới nhập từ bên phải. Với mã mà hành vi này là ngược lại
giozh

1
Đã trả lời ở đây: stackoverflow.com/questions/10886669/…
Carsten,

Câu trả lời:


276

CẬP NHẬT Cho Android v19 + xem liên kết này qua @Sandra

Bạn có thể tạo hoạt ảnh của riêng bạn. Đặt các tệp XML hoạt ảnh vàores > 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>

bạn có thể thay đổi thời lượng thành thời gian hoạt ảnh ngắn

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

hoặc thời gian hoạt hình dài

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

USAGE (lưu ý rằng thứ tự bạn gọi các phương thức trong giao dịch rất quan trọng. Thêm hoạt ảnh trước khi bạn gọi .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
chỉ cần sử dụng các hoạt ảnh xml này khi thay thế các phân đoạn, tức là :gmentTransaction.setCustomAnimations (R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right); mảnhTransaction.replace (R.id.content_frame, fragDettRisorsa); mảnhTransaction.addToBackStack (null); mảnhTransaction.commit ();
moondroid

11
không rõ tên phim hoạt hình nói của nó: dịch
Hirak Chhatbar

9
Nó không hoạt động ... gây ra "java.lang.RuntimeException: Unknown animator name: translate". Giải pháp này đã làm việc cho tôi. trickyandroid.com/fragment-translate-animation
Ataru

27
Theo tôi, thời lượng 700là một chút cho những hình ảnh động như vậy. Khung Android có 3 cài đặt trước cho thời gian: android:duration="@android:integer/config_longAnimTime", android:duration="@android:integer/config_mediumAnimTime"android:duration="@android:integer/config_shortAnimTime", trong đó tương ứng với 500, 400 và 200. Tôi đoán đơn vị là mili giây, nhưng tôi không chắc chắn.
Krøllebølle

6
chỉ hoạt động khi sử dụng mảnh vỡ hỗ trợ (android.support.v4.app.Fragment)
Aviv Ben Shabat

37

Có ba cách để giao dịch hoạt ảnh trong phân mảnh.

Chuyển tiếp

Vì vậy, cần sử dụng một trong các Chuyển đổi tích hợp, sử dụng phương thức setTranstion ():

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

Hoạt ảnh tùy chỉnh

Bạn cũng có thể tùy chỉnh hoạt ảnh bằng cách sử dụng phương thức 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"/>

Nhiều hoạt ảnh

Cuối cùng, cũng có thể bắt đầu nhiều hoạt ảnh phân mảnh trong một giao dịch duy nhất. Điều này cho phép tạo ra một hiệu ứng khá thú vị khi một mảnh trượt lên và mảnh kia trượt xuống cùng một lúc:

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

Để biết thêm chi tiết, bạn có thể truy cập URL

Lưu ý: - Bạn có thể kiểm tra hoạt ảnh theo yêu cầu của bạn vì ở trên có thể có vấn đề.


1
Bạn đang sử dụng giá trị được mã hóa cứng tuyệt đối. Đoạn trước đó sẽ biến mất ở giữa màn hình để hiển thị độ phân giải cao hơn.
TheLibrarian

@TheLibrarianCz đây chỉ là ví dụ
duggu

1
Nó có và nó không phải.
TheLibrarian

nó phụ thuộc vào việc một số người muốn ăn bằng thìa từ ví dụ trên hoặc lấy bài học mà họ có thể đạt được với ví dụ.
duggu

có gì trong biến m_topFragment
Prince

6

Tôi gặp vấn đề tương tự, tôi đã sử dụng giải pháp đơn giản

1) tạo slide_out_right.xml trong thư mục hoạt ảnh

  <?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) tạo slide_in_left.xml trong thư mục hoạt ảnh

<?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) chỉ cần sử dụng phân đoạn giao dịch setCustomeAnimations () với hai xml tùy chỉnh và hai xml mặc định cho hoạt ảnh như sau: -

 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>

hướng = xuống

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

hướng = lên

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

2

Đây là một giải pháp khác mà tôi sử dụng:

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

Việc sử dụng lớp. Giả sử bạn có hai phân đoạn (phân đoạn danh sách và chi tiết) như được hiển thị bên dưới

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

Sử dụng

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

Bạn có thể sử dụng chức năng CustomAnimator.reversePrevious();để xem trước đó khi người dùng nhấn lại.


1
bạn có chắc mình đang sử dụng Fragment của android không? =) có vẻ như đang sử dụng hệ thống dựa trên chế độ xem quản lý phân mảnh tùy chỉnh)
hôn
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.