Làm sinh động quá trình chuyển đổi giữa các mảnh


284

Tôi đang cố gắng làm sinh động quá trình chuyển đổi giữa các mảnh. Tôi đã nhận được câu trả lời từ các phân đoạn và hoạt hình Android sau đây

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

Và R.anim.slide_in_left của tôi

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

Nhưng khi tôi thử nó

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)

Có ý kiến ​​gì không? Khi tôi kiểm tra tham chiếu API Honeycomb translatelà có. Tôi đã bỏ lỡ cái gì?
Có cách nào khác để làm sinh động quá trình chuyển đổi giữa các mảnh không? Cảm ơn bạn


sử dụng ĐỘNG VẬT --- không phải Hoạt hình! sử dụng android.R.ANIMATOR.fade_in hoạt động, KHÔNG sử dụng android.R.ANIM.fade_in - nó có hành vi BUGS
user1269737

Câu trả lời:


347

Bạn cần sử dụng android.animationkhung công tác mới (hoạt hình đối tượng) FragmentTransaction.setCustomAnimationscũng như FragmentTransaction.setTransition.

Đây là một ví dụ về việc sử dụng setCustomAnimationstừ FragmentHideShow.java của ApiDemos :

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

và đây là XML của trình hoạt hình có liên quan từ 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" />

Lưu ý rằng bạn có thể kết hợp nhiều trình hoạt hình bằng cách sử dụng <set>khung hoạt hình cũ hơn.


BIÊN TẬP : Vì mọi người đang hỏi về slide-in / slide-out, tôi sẽ bình luận về điều đó ở đây.

Trượt vào và trượt ra

Bạn dĩ nhiên có thể animate translationX, translationY, x, và ytài sản, nhưng nhìn chung các slide liên quan đến hiệu ứng động nội dung đến và đi từ tắt màn hình. Theo như tôi biết thì không có bất kỳ thuộc tính chuyển tiếp nào sử dụng các giá trị tương đối. Tuy nhiên, điều này không ngăn cản bạn tự viết chúng. Hãy nhớ rằng hoạt ảnh thuộc tính chỉ đơn giản yêu cầu các phương thức getter và setter trên các đối tượng bạn đang hoạt hình (trong trường hợp này là các khung nhìn), vì vậy bạn chỉ có thể tạo riêng của mình getXFractionsetXFractioncác phương thức trên lớp con khung nhìn của bạn, như thế này:

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

Bây giờ bạn có thể làm động các thuộc tính 'xFraction', như thế này:

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

Lưu ý rằng nếu đối tượng bạn đang hoạt hình không có cùng chiều rộng với cha mẹ của nó, mọi thứ sẽ không hoàn toàn đúng, do đó bạn có thể cần phải điều chỉnh việc triển khai thuộc tính của mình cho phù hợp với trường hợp sử dụng của mình.


8
Tôi đã làm mờ fade_in và fadeDef để hoạt động, nhưng những cái khác trong / res / animator đều báo lỗi. Và không ai trong số họ thậm chí dường như là để trượt vào và trượt ra. Tôi đã cố gắng viết xml của riêng mình để làm điều này, nhưng tất cả những gì tôi kết thúc chỉ là những mảnh vỡ trên đầu những mảnh vỡ. Xin vui lòng giúp đỡ thêm?
Dave MacLean

Còn bản dịch thì sao? Làm thế nào để bạn thực hiện một bản dịch với các giá trị theo tỷ lệ phần trăm trong objectAnimator xác định trong XML, làm ơn? Tôi đã không thành công trong việc tạo hiệu ứng AdaptorViewFlipper trong khi lật với hình động trượt dọc được xác định trong xml ...
GBouerat

6
Tôi nhận được 11-19 10: 27: 50.912: W / PropertyValuesHolder (23107): Phương thức setXFraction () với kiểu float không tìm thấy trên lớp mục tiêu android.widget.FrameLayout. Nhưng trong XML của tôi, tôi có chế độ xem tùy chỉnh MyFrameLayout. Có ý kiến ​​gì không?
sủa

13
Thật ra, Roman, lời khuyên cũng nên đi theo một cách khác: Khi sử dụng Thư viện hỗ trợ, bạn cần sử dụng khung hoạt hình cũ (android.R.anim) với FragmentTransaction.setCustomAnimations ao
pjv

1
@RomanNurik câu trả lời này hoạt động rất tốt trên hầu hết các thiết bị, nhưng đối với một số người dùng (cụ thể là trên một số điện thoại Samsung Galaxy S3 / 4), độ rộng không được báo cáo trong các hoạt hình vì một số lý do, khiến cho đoạn này không bao giờ xuất hiện. Tôi đã có thể làm cho nó hoạt động cho những người dùng đó bằng cách sử dụng OnPredrawListener như được hiển thị ở đây: meefasoni9891.blogspot.com/2014/06/ Thẻ
ajpolt

188

Tôi đã làm theo cách này:

Thêm phương pháp này để thay thế các đoạn bằng Ảnh động :

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

Bạn phải thêm bốn hình ảnh động trong anim thư mục đó là với tài nguyên :

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>

Đầu ra:

nhập mô tả hình ảnh ở đây

Xong rồi .


14
Giải pháp tuyệt vời. Tuy nhiên tôi không chắc tại sao bạn đổi hướng sang RTL. Phương pháp của tôi:.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right)
zed

2
Giải pháp tuyệt vời. Cách tiếp cận tương tự và các tệp hoạt hình tương tự hoạt động để chuyển tiếp giữa các hoạt động.
Stan

1
@MikeZriel, res -> hoạt hình -> đặt xml của bạn vào đây
Hiren Patel

3
Cảm ơn Hiren, tôi thay đổi tốc độ (700) thành (300) tốt hơn nhiều và giống với iOS hơn
Mike Zriel

3
LOL, tôi đã trở lại với giải pháp. Tôi đã nhập android.app.fragment và FragmentManager trên mỗi lớp java. Sau khi kiểm tra một số tài liệu, tôi thấy rằng sử dụng thư viện 'setCustomAnimations ()' cần phải nhập thư viện android.support.v4. điều quan trọng để nói rằng đó phải là 'support.v4.app'! Tôi đã thay thế tất cả các phương thức 'getFragmentManager ()' bằng 'getSupportFragmentManager ()' và tất cả việc nhập 'android.app.Fragment / FragmentManager ...' thành 'android.support.v4.app ....', sau đó Hoạt hình bắt đầu hoạt động tốt mà không gặp sự cố ... Nếu các bạn bị mắc kẹt trong các trường hợp tương tự, hãy đọc giải pháp của tôi. Thx Hiren Patel xD
KoreanXcodeWorker

58

Nếu bạn có đủ khả năng ràng buộc bản thân chỉ với Lollipop và sau đó, điều này có vẻ là một mẹo nhỏ:

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

Hi vọng điêu nay co ich.


1
Mặc dù điều đó sẽ đạt được điều đó trên Lollipop, nhưng hầu như không thực tế vì tỷ lệ thiết bị chạy Lollipop là không đáng kể (hiện tại 1,6% thiết bị Android đang chạy Lollipop).
Eran Goldin

1
new Slide(...): cuộc gọi yêu cầu API cấp 21
Chintan Soni

getKey () là viết tắt của từ gì?
Alvaro

13
@EranGoldin Không có gì tồn tại mãi mãi .. bạn sẽ chế giễu một giải pháp duy nhất của Android 2.0+ ngày hôm nay chứ?
Tom

@Tom bạn có một điểm. Tuy nhiên, khi ứng dụng của bạn có lượng người dùng lớn, bạn không thể tăng cấp API. Nếu hầu hết người dùng của bạn sẽ không thể chạy ứng dụng của bạn sau đó nữa, thì đó không phải là giải pháp nào cả.
Eran Goldin

47

Câu trả lời của Nurik rất hữu ích, nhưng tôi không thể làm cho nó hoạt động cho đến khi tôi tìm thấy . Nói tóm lại, nếu bạn đang sử dụng thư viện tương thích (ví dụ: SupportFragmentManager thay vì FragmentManager), cú pháp của các tệp hoạt hình XML sẽ khác nhau.


28

Đây là một slide hoạt hình vào / ra giữa các đoạn:

FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.setCustomAnimations(R.animator.enter_anim, R.animator.exit_anim);
transaction.replace(R.id.listFragment, new YourFragment());
transaction.commit();

Chúng tôi đang sử dụng một objectAnimator.

Dưới đây là hai tệp xml trong thư mục con hoạt hình .

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>

Tôi hy vọng điều đó sẽ giúp được ai đó.


37
di chuyển quan điểm cho 2000 px, là một giải pháp rất xấu.
carlo.marinangeli

4
Lối thoát_anim chỉ "bật" ra khỏi màn hình đối với tôi, nó không hoạt động trở lại trên màn hình. Có ý kiến ​​gì không? Tôi đang sử dụng.setCustomAnimations(R.animator.slide_in_left, R.animator.slide_out_right, R.animator.slide_in_left, R.animator.slide_out_right)
Mr Pablo

@MrPablo, lý do có lẽ là bạn chưa sao chép mã ở trên. setCustomAnimations nên được gọi trước phương thức thay thế.
Galya

Trong trường hợp này, nếu tôi thay thế đoạn khác bằng hình động và tôi thu nhỏ ứng dụng ngay lập tức trước khi hết thời gian hoạt hình hoặc hết lần này trở lại ứng dụng, nó sẽ hiển thị đoạn trước và đoạn hiện tại song song.
Hoàng tử

23

Đối với bất kỳ ai khác bị bắt, hãy đảm bảo setCustomAnimations được gọi trước lệnh gọi để thay thế / thêm khi xây dựng giao dịch.


12

Việc triển khai SDK Android của FragmentTransaction muốn một Animatorthư viện hỗ trợ muốn một lúc Animation, đừng hỏi tôi tại sao nhưng sau khi nhận xét của strangeluk, tôi đã xem xét thư viện hỗ trợ và mã android 4.0.3. Android SDK sử dụng loadAnimator()và sử dụng thư viện hỗ trợloadAnimation()


7

Hãy thử sử dụng giải pháp đơn giản và nhanh chóng này. Android cung cấp một số animations mặc định .

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

Đầu ra:

nhập mô tả hình ảnh ở đây


Woow .. đây sẽ là câu trả lời được chấp nhận !! Một giải pháp đơn giản và thanh lịch. Nó rất mượt so với các câu trả lời gợi ý khác
Chathura Buddhaika
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.