Tôi đang cố gắng thay thế GridView bằng RecyclerView mới (sử dụng GridLayoutManager) nhưng có vẻ như nó không tương thích tốt với gridLayoutAnimation (ClassCastException: LayoutAnimationController$AnimationParameters cannot be cast to GridLayoutAnimationController$AnimationParameters
). Nó hoạt động với một hoạt hình bố trí thường xuyên, nhưng vì nó là một mạng lưới, phải mất quá nhiều thời gian để hoàn thành trên máy tính bảng.Làm cách nào để sử dụng GridLayoutAnimation trong RecyclerView?
Điều tôi đang cố thực hiện tương tự với Hierarchical Timing. Nếu bạn nhìn vào video ví dụ, nó sẽ hiển thị hoạt ảnh bố cục từ trên xuống bên trái theo chiều dọc theo đường chéo. Một hoạt ảnh bố cục thông thường sẽ thực thi hàng hoạt ảnh sau hàng, do đó mất quá nhiều thời gian để hoàn thành trên các lưới lớn hơn (ví dụ: máy tính bảng). Tôi cũng đã cố gắng khám phá ItemAnimator, nhưng điều đó sẽ chỉ chạy hoạt ảnh trên tất cả các ô cùng một lúc giống như trong ví dụ "Don't".
Có cách nào để thực hiện hoạt ảnh bố cục lưới này trong RecyclerView không?
Đây là gridview_layout_animation.xml:
<!-- replace gridLayoutAnimation with layoutAnimation and -->
<!-- replace column- and rowDelay with delay for RecyclerView -->
<gridLayoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:columnDelay="15%"
android:rowDelay="15%"
android:animation="@anim/grow_in"
android:animationOrder="normal"
android:direction="top_to_bottom|left_to_right"
android:interpolator="@android:interpolator/linear"
/>
Và đây là grow_in.xml hoạt hình:
<set android:shareInterpolator="false"
xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:interpolator="@android:interpolator/decelerate_quint"
android:fromXScale="0.0"
android:toXScale="1.0"
android:fromYScale="0.0"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="true"
android:duration="400"
android:startOffset="200"
/>
</set>
EDIT: Dựa trên câu trả lời của Galaxas0, here là một giải pháp chỉ yêu cầu bạn sử dụng chế độ xem tùy chỉnh mở rộng RecyclerView
. Về cơ bản chỉ ghi đè phương thức attachLayoutAnimationParameters()
. Với công cụ <gridLayoutAnimation>
hoạt động như với GridView.
public class GridRecyclerView extends RecyclerView {
public GridRecyclerView(Context context) {
super(context);
}
public GridRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public GridRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void setLayoutManager(LayoutManager layout) {
if (layout instanceof GridLayoutManager){
super.setLayoutManager(layout);
} else {
throw new ClassCastException("You should only use a GridLayoutManager with GridRecyclerView.");
}
}
@Override
protected void attachLayoutAnimationParameters(View child, ViewGroup.LayoutParams params, int index, int count) {
if (getAdapter() != null && getLayoutManager() instanceof GridLayoutManager){
GridLayoutAnimationController.AnimationParameters animationParams =
(GridLayoutAnimationController.AnimationParameters) params.layoutAnimationParameters;
if (animationParams == null) {
animationParams = new GridLayoutAnimationController.AnimationParameters();
params.layoutAnimationParameters = animationParams;
}
int columns = ((GridLayoutManager) getLayoutManager()).getSpanCount();
animationParams.count = count;
animationParams.index = index;
animationParams.columnsCount = columns;
animationParams.rowsCount = count/columns;
final int invertedIndex = count - 1 - index;
animationParams.column = columns - 1 - (invertedIndex % columns);
animationParams.row = animationParams.rowsCount - 1 - invertedIndex/columns;
} else {
super.attachLayoutAnimationParameters(child, params, index, count);
}
}
}
Ông có thể vui lòng giải thích như thế nào? Tôi đã thử làm điều đó với ItemAnimator mặc định cũng như tải xuống các ví dụ về [ItemAnimators] khác nhau (https://github.com/gabrielemariotti/RecyclerViewItemAnimators/tree/master/library/src/main/java/it/gmariotti/recyclerview/itemanimator) nhưng tôi không thể có vẻ như là hình ảnh động mà tôi đang tìm kiếm. – Musenkishi
Bạn đã chắc chắn không sử dụng 'notifyDataSetChanged()', và thay vào đó sử dụng 'notifyItemRangeAdded()' và 'notifyItemRangeRemoved()'? Điều này sẽ luôn kích hoạt hoạt ảnh đầu tiên tải. –
Có, tôi đã thử sử dụng 'notifyItemRangeAdded()' nhưng như tôi đã mô tả ở trên, nó không cho tôi hành vi mong muốn. 'notifyItemRangeAdded()' sẽ chạy hoạt ảnh trên hàng đầu tiên và ** không ** bắt đầu trên hàng thứ hai cho đến khi tất cả các ô trong ô đầu tiên đã bắt đầu hoạt ảnh của nó. Hình ảnh động mà tôi có thể nhận được từ '' có thể đi theo đường chéo trên các hàng, có nghĩa là nó có thể bắt đầu làm động một số hàng cùng một lúc. Về cơ bản làm cho tất cả các ô trong lưới xuất hiện trong một làn sóng từ trên xuống dưới bên phải. –
Musenkishi