Android Fragment và hoạt hình


265

Bạn nên triển khai loại trượt như ví dụ như ứng dụng khách Honeycomb Gmail sử dụng như thế nào?

Có thể TransactionManagertự động xử lý việc này bằng cách thêm và xóa các Mảnh vỡ, thật khó để kiểm tra điều này do trình giả lập là trình chiếu :)

Câu trả lời:


388

Để tạo hiệu ứng cho quá trình chuyển đổi giữa các đoạn hoặc để tạo hiệu ứng cho quá trình hiển thị hoặc ẩn một đoạn bạn sử dụng Fragment Managerđể tạoFragment Transaction .

Trong mỗi Giao dịch phân mảnh, bạn có thể chỉ định hoạt ảnh trong và ngoài sẽ được sử dụng để hiển thị và ẩn tương ứng (hoặc cả hai khi thay thế được sử dụng).

Đoạn mã sau cho thấy cách bạn sẽ thay thế một đoạn bằng cách trượt ra một đoạn và trượt đoạn kia vào vị trí của nó.

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

Để đạt được điều tương tự với việc ẩn hoặc hiển thị một đoạn bạn chỉ cần gọi ft.showhoặc ft.hidechuyển qua Đoạn bạn muốn hiển thị hoặc ẩn tương ứng.

Để tham khảo, các định nghĩa hoạt hình XML sẽ sử dụng objectAnimatorthẻ. Một ví dụ về slide_in_left có thể trông giống như thế này:

<?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
Khi tôi thử nó, nó hiển thị RuntimeException: Tên hoạt hình không xác định: dịch .
Labeeb Panampullan

3
Đảm bảo rằng các hình động được xác định trong slide_in_left và bên phải được xây dựng bằng cách sử dụng một bộ định nghĩa objectAnimator thay vì định nghĩa hoạt hình cũ.
Reto Meier

7
Điều đó đã giúp rất nhiều. Tôi đã đi đúng hướng nhưng không đi được đến đó. Đối với những người đọc khác, bạn cũng có thể có android: interpolator làm thuộc tính, với thuộc tính yêu thích của bạn được chỉ định (chẳng hạn như "@android: interpolator / linear"). Nó mặc định là "@android: interpolator / speedate_decelerate".
Dave MacLean

6
Tôi đang nhắm mục tiêu API cấp 7 với các API tương thích. Có cách nào để tôi làm động các mảnh vỡ không?
Jarrod Smith

5
@JarrodSmith bạn có thể thử sử dụng thư viện tương thích như NineOldAndroids để đưa API Honeycomb xuống Eclair.
Ông S

249

Nếu bạn không phải sử dụng thư viện hỗ trợ thì hãy xem câu trả lời của Roman .

Nhưng nếu bạn muốn sử dụng thư viện hỗ trợ, bạn phải sử dụng khung hoạt hình cũ như được mô tả dưới đây.

Sau khi tham khảo câu trả lời của Reto và người mù, tôi đã nhận được đoạn mã sau hoạt động.

Các mảnh vỡ xuất hiện trượt từ bên phảitrượt ra bên trái khi nhấn trở lại.

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

Thứ tự là quan trọng. Điều này có nghĩa là bạn phải gọi setCustomAnimations()trước replace()hoặc hình ảnh động sẽ không có hiệu lực!

Tiếp theo các tệp này phải được đặt trong thư mục 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>

Thời lượng của hình ảnh động có thể được thay đổi thành bất kỳ giá trị mặc định nào như @android:integer/config_shortAnimTimehoặc bất kỳ số nào khác.

Lưu ý rằng nếu ở giữa các thay thế phân đoạn, một sự thay đổi cấu hình xảy ra (ví dụ như xoay vòng) thì hành động quay lại không hoạt hình. Đây là một lỗi tài liệu vẫn còn tồn tại trong rev 20 của thư viện hỗ trợ.


47
Điều này chỉ cứu tôi. Lưu ý, chú ý đến thứ tự là rất quan trọng , trong đó, tự nhiên, tôi đã bỏ lỡ lần đầu tiên. Điều này có nghĩa là bạn phải gọi setCustomAnimations () trước khi thay thế ().
Stephen Kidson

3
Tôi đã cố gắng thực hiện trên các đoạn của mình. Tôi đã viết tất cả mọi thứ như bạn đã đề cập nhưng logcat nói: unkn tên hoạt hình dịch Làm thế nào tôi có thể khắc phục vấn đề này? Nhân tiện, tôi đang gọi đoạn của mình trên Ngăn kéo Điều hướng (Menu Trượt)
Zafer Celaloglu

Hoạt động rất tốt nhưng hóa ra việc xây dựng công cụ này với các công cụ xây dựng 21.1 tạo ra lỗi "Tên tệp không hợp lệ: chỉ chứa các chữ cái và chữ số viết thường ([a-z0-9_.])". Tôi đề nghị chỉnh sửa tên tệp trong câu trả lời cho pop_enter.xml và pop_exit.xml.
smichak

Giải pháp tuyệt vời và nó hoạt động tuyệt vời khi tôi nhấn nút quay lại. Tôi chỉ có một câu hỏi: Nếu tôi muốn tạo backButton tùy chỉnh, tôi nên gọi mã nào để sao chép hành vi từ nút quay lại?
Thomas Teilmann

1
Thomas nếu bạn muốn quay lại, bạn nên triển khai biểu mẫu này: .setCustomAnimations (R.anim.pop_enter, R.anim.pop_exit, R.anim.enter, R.anim.exit)
Alex Zaraos

26

Tôi thực sự khuyên bạn nên sử dụng điều này thay vì tạo tệp hoạt hình vì đó là một giải pháp tốt hơn nhiều. Android Studio đã cung cấp mặc định animation bạn có thể sử dụng mà không cần tạo bất kỳ tệp XML mới nào. Tên của hình ảnh động là android.R.anim.slide_in_leftandroid.R.anim.slide thừng_right và bạn có thể sử dụng chúng như sau:

FragmentTransaction.setCustomAnimations (android.R.anim.slide_in_left, android.R.anim.slide thừng_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


1
android.R ... "Android Studio Cung cấp hình ảnh động mặc định", không dành cho android studio, nó cũng có thể hoạt động trong nhật thực, android.R là Android cụ thể. Và bằng cách bạn không chia sẻ thông tin những gì apis có này. Bởi vì công cụ trên android.R là khác nhau trên apis khác nhau.
steve moretz

@stevemoretz thaxs bro Tôi đã đồng ý quan điểm của bạn .. Tôi sẽ sửa và cập nhật câu trả lời của mình ...
Gowthaman M

5

Thư viện hỗ trợ đã sửa đổi của tôi hỗ trợ bằng cách sử dụng cả Xem hoạt hình (tức là <translate>, <rotate>) và Đối tượng hoạt hình (tức là <objectAnimator>) cho Chuyển tiếp phân đoạn. Nó được thực hiện với NineOldAndroids . Tham khảo tài liệu của tôi trên github để biết chi tiết.


2

Đối với tôi, tôi cần giao diện xem:

trong -> vuốt từ phải sang

ra -> vuốt sang trái

Ở đây làm việc cho tôi mã:

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 tựa_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>

mã giao dịch:

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 dường như đang làm rung chuyển quá trình chuyển đổi với những hình ảnh động đó (đặc biệt là các bản dịch)
Gabriel De Oliveira Rohden

@GabrielDeOliveiraRohden đối với tôi không phải trong tất cả các casses
Serg Burlaka

1

Tôi giải quyết theo cách này

Animation anim = AnimationUtils.loadAnimation(this, R.anim.slide);
fg.startAnimation(anim);
this.fg.setVisibility(View.VISIBLE); //fg is a View object indicate fragment
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.