RecyclerView 항목이 나타날 때 어떻게 애니메이션을 적용 할 수 있습니까?
기본 아이템 애니메이터는 리사이클 러 데이터가 설정된 후 데이터가 추가되거나 제거 될 때만 애니메이션을 만듭니다. 저는 새로운 응용 프로그램을 개발 중이며 시작할 곳이 없습니다.
이것을 달성하는 방법에 대한 아이디어가 있습니까?
RecyclerView 항목이 나타날 때 어떻게 애니메이션을 적용 할 수 있습니까?
기본 아이템 애니메이터는 리사이클 러 데이터가 설정된 후 데이터가 추가되거나 제거 될 때만 애니메이션을 만듭니다. 저는 새로운 응용 프로그램을 개발 중이며 시작할 곳이 없습니다.
이것을 달성하는 방법에 대한 아이디어가 있습니까?
답변:
XML만으로 간단하게 제작
res / anim / layout_animation.xml
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@anim/item_animation_fall_down"
android:animationOrder="normal"
android:delay="15%" />
res / anim / item_animation_fall_down.xml
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500">
<translate
android:fromYDelta="-20%"
android:toYDelta="0"
android:interpolator="@android:anim/decelerate_interpolator"
/>
<alpha
android:fromAlpha="0"
android:toAlpha="1"
android:interpolator="@android:anim/decelerate_interpolator"
/>
<scale
android:fromXScale="105%"
android:fromYScale="105%"
android:toXScale="100%"
android:toYScale="100%"
android:pivotX="50%"
android:pivotY="50%"
android:interpolator="@android:anim/decelerate_interpolator"
/>
</set>
레이아웃 및 recylcerview에서 다음과 같이 사용하십시오.
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layoutAnimation="@anim/layout_animation"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
recyclerView.scheduleLayoutAnimation()
데이터 세트가 변경된 후 호출해야합니다 . 그렇지 않으면 애니메이션이 작동하지 않습니다.
편집하다 :
ItemAnimator 설명서 에 따르면 :
이 클래스는 어댑터가 변경 될 때 항목에서 발생하는 애니메이션을 정의합니다.
따라서 항목을 하나씩 추가 RecyclerView
하고 각 반복에서보기를 새로 고치지 않으면 ItemAnimator
필요에 대한 해결책 이라고 생각하지 않습니다 .
RecyclerView
CustomAdapter를 사용하여 항목을 표시 할 때 애니메이션을 적용하는 방법은 다음과 같습니다 .
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder>
{
private Context context;
// The items to display in your RecyclerView
private ArrayList<String> items;
// Allows to remember the last item shown on screen
private int lastPosition = -1;
public static class ViewHolder extends RecyclerView.ViewHolder
{
TextView text;
// You need to retrieve the container (ie the root ViewGroup from your custom_item_layout)
// It's the view that will be animated
FrameLayout container;
public ViewHolder(View itemView)
{
super(itemView);
container = (FrameLayout) itemView.findViewById(R.id.item_layout_container);
text = (TextView) itemView.findViewById(R.id.item_layout_text);
}
}
public CustomAdapter(ArrayList<String> items, Context context)
{
this.items = items;
this.context = context;
}
@Override
public CustomAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_item_layout, parent, false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position)
{
holder.text.setText(items.get(position));
// Here you apply the animation when the view is bound
setAnimation(holder.itemView, position);
}
/**
* Here is the key method to apply the animation
*/
private void setAnimation(View viewToAnimate, int position)
{
// If the bound view wasn't previously displayed on screen, it's animated
if (position > lastPosition)
{
Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left);
viewToAnimate.startAnimation(animation);
lastPosition = position;
}
}
}
그리고 custom_item_layout은 다음과 같습니다.
<FrameLayout
android:id="@+id/item_layout_container"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/item_layout_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeightSmall"/>
</FrameLayout>
CustomAdapters 및에 대한 자세한 내용은 공식 문서에 대한RecyclerView
이 교육을 참조하십시오 .
빠른 스크롤 문제
이 방법을 사용하면 빠른 스크롤 문제가 발생할 수 있습니다. 애니메이션이 진행되는 동안 뷰를 재사용 할 수 있습니다. 이를 피하려면 분리 할 때 애니메이션을 지우는 것이 좋습니다.
@Override
public void onViewDetachedFromWindow(final RecyclerView.ViewHolder holder)
{
((CustomViewHolder)holder).clearAnimation();
}
CustomViewHolder에서 :
public void clearAnimation()
{
mRootLayout.clearAnimation();
}
이전 답변 :
Gabriele Mariotti의 저장소를 살펴보십시오 . 필요한 것을 찾을 수있을 것입니다. 그는 RecycleInView에 간단한 ItemAnimators를 제공합니다 (예 : SlideInItemAnimator 또는 SlideScaleItemAnimator).
onViewDetachedFromWindow
하고 호출 clearAnimation
합니다. 문제는 RecyclerView가 뷰를 재사용하려고 할 때 애니메이션이 실행되고 있다는 것입니다.
Recyclerview
아래 코드에 표시된 것처럼 항목이 처음 나타날 때 페이드 인 애니메이션을했습니다 . 아마도 이것은 누군가에게 유용 할 것입니다.
private final static int FADE_DURATION = 1000; //FADE_DURATION in milliseconds
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.getTextView().setText("some text");
// Set the view to fade in
setFadeAnimation(holder.itemView);
}
private void setFadeAnimation(View view) {
AlphaAnimation anim = new AlphaAnimation(0.0f, 1.0f);
anim.setDuration(FADE_DURATION);
view.startAnimation(anim);
}
setFadeAnimation()
다음 setScaleAnimation()
항목으로 대체 하여 항목의 크기를 조정하여 모양을 애니메이션으로 만들 수도 있습니다 .
private void setScaleAnimation(View view) {
ScaleAnimation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
anim.setDuration(FADE_DURATION);
view.startAnimation(anim);
}
위의 코드에는 RecyclerView
항목 을 스크롤 할 때 항상 페이드 또는 스케일되는 일부 사마귀가 있습니다. 원하는 경우 애니메이션을 포함하는 조각 또는 활동 RecyclerView
이 처음 생성 될 때 애니메이션이 발생하도록 코드를 추가 할 수 있습니다 (예 : 생성시 시스템 시간을 확보하고 첫 번째 FADE_DURATION 밀리 초 동안 애니메이션 만 허용).
애니메이션을 한 번만 실행하도록 pbm의 답변 에서 애니메이션을 거의 modification
만들지 않았습니다.
다시 말해서 Animation appear with you scroll down only
private int lastPosition = -1;
private void setAnimation(View viewToAnimate, int position) {
// If the bound view wasn't previously displayed on screen, it's animated
if (position > lastPosition) {
ScaleAnimation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
anim.setDuration(new Random().nextInt(501));//to make duration random number between [0,501)
viewToAnimate.startAnimation(anim);
lastPosition = position;
}
}
그리고 onBindViewHolder
함수 를 호출
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.getTextView().setText("some text");
// call Animation function
setAnimation(holder.itemView, position);
}
lastPosition
ITS의 값을 그 시작되도록 렌더링 조회수 나타내고 -1
, 새로운 뷰 우리가 애니메이션을 시작 위치 증가 렌더링되는 모든 시간
다음 과 같은 android:layoutAnimation="@anim/rv_item_animation"
속성을 추가 할 수 있습니다 RecyclerView
.
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutAnimation="@anim/layout_animation_fall_down"
/>
훌륭한 기사를 보내 주셔서 감사합니다 : https://proandroiddev.com/enter-animation-using-recyclerview-and-layoutanimation-part-1-list-75a874a5d213
당신은 전체 라이브러리가 필요하지 않습니다, 그 클래스는 충분합니다. 그런 다음 애니메이터를 제공하는 Adapter 클래스를 구현하면 다음과 같습니다.
@Override
protected Animator[] getAnimators(View view) {
return new Animator[]{
ObjectAnimator.ofFloat(view, "translationY", view.getMeasuredHeight(), 0)
};
}
@Override
public long getItemId(final int position) {
return getWrappedAdapter().getItemId(position);
}
스크롤 할 때 맨 아래부터 항목이 표시되고 빠른 스크롤 문제를 피할 수 있습니다.
재 순환기보기에서 항목이 어댑터에 바인드 될 때 항목을 애니메이션하면 재 순환기보기의 항목이 다른 속도로 애니메이션 될 수 있으므로 최상의 아이디어가 아닐 수 있습니다. 내 경우에는 recyclerview의 끝에있는 항목이 더 빨리 자신의 위치에 애니메이션을 적용 한 다음 상단에있는 항목이 더 멀리 이동하여 어수선하게 보입니다.
각 항목을 recyclerview로 애니메이션하는 데 사용한 원래 코드는 여기에서 찾을 수 있습니다.
http://frogermcs.github.io/Instagram-with-Material-Design-concept-is-getting-real/
그러나 링크가 끊어 질 경우 코드를 복사하여 붙여 넣습니다.
1 단계 : 애니메이션을 한 번만 실행하도록 onCreate 메소드 내에서이를 설정하십시오.
if (savedInstanceState == null) {
pendingIntroAnimation = true;
}
2 단계 : 애니메이션을 시작하려는 메서드에이 코드를 넣어야합니다.
if (pendingIntroAnimation) {
pendingIntroAnimation = false;
startIntroAnimation();
}
링크에서 작성자는 도구 모음 아이콘에 애니메이션을 적용하므로 다음과 같은 방법으로 도구 모음에 넣습니다.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
inboxMenuItem = menu.findItem(R.id.action_inbox);
inboxMenuItem.setActionView(R.layout.menu_item_view);
if (pendingIntroAnimation) {
pendingIntroAnimation = false;
startIntroAnimation();
}
return true;
}
3 단계 : 이제 startIntroAnimation ()의 논리를 작성하십시오.
private static final int ANIM_DURATION_TOOLBAR = 300;
private void startIntroAnimation() {
btnCreate.setTranslationY(2 * getResources().getDimensionPixelOffset(R.dimen.btn_fab_size));
int actionbarSize = Utils.dpToPx(56);
toolbar.setTranslationY(-actionbarSize);
ivLogo.setTranslationY(-actionbarSize);
inboxMenuItem.getActionView().setTranslationY(-actionbarSize);
toolbar.animate()
.translationY(0)
.setDuration(ANIM_DURATION_TOOLBAR)
.setStartDelay(300);
ivLogo.animate()
.translationY(0)
.setDuration(ANIM_DURATION_TOOLBAR)
.setStartDelay(400);
inboxMenuItem.getActionView().animate()
.translationY(0)
.setDuration(ANIM_DURATION_TOOLBAR)
.setStartDelay(500)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
startContentAnimation();
}
})
.start();
}
내가 선호하는 대안 :
오히려 recyclerview 내부의 항목 대신 전체 recyclerview에 애니메이션을 적용하십시오.
1 단계와 2 단계는 동일하게 유지됩니다.
3 단계에서 API 호출이 데이터와 함께 반환되는 즉시 애니메이션을 시작합니다.
private void startIntroAnimation() {
recyclerview.setTranslationY(latestPostRecyclerview.getHeight());
recyclerview.setAlpha(0f);
recyclerview.animate()
.translationY(0)
.setDuration(400)
.alpha(1f)
.setInterpolator(new AccelerateDecelerateInterpolator())
.start();
}
이렇게하면 전체 recyclerview에 애니메이션이 적용되어 화면 하단에서 날아갑니다.
latestPostRecyclerview
?
2019 년에는 모든 아이템 애니메이션을 ItemAnimator에 넣는 것이 좋습니다.
리사이클 러 뷰에서 애니메이터를 선언하는 것으로 시작하겠습니다.
with(view.recycler_view) {
adapter = Adapter()
itemAnimator = CustomAnimator()
}
그런 다음 사용자 정의 애니메이터를 선언하십시오.
class CustomAnimator() : DefaultItemAnimator() {
override fun animateAppearance(
holder: RecyclerView.ViewHolder,
preInfo: ItemHolderInfo?,
postInfo: ItemHolderInfo): Boolean{} // declare what happens when a item appears on the recycler view
override fun animatePersistence(
holder: RecyclerView.ViewHolder,
preInfo: ItemHolderInfo,
postInfo: ItemHolderInfo): Boolean {} // declare animation for items that persist in a recycler view even when the items change
}
위의 것들과 유사하게, 사라짐 animateDisappearance
, 추가 animateAdd
, 변화 animateChange
및 이동을 위한 것이 있습니다 animateMove
.
한 가지 중요한 점은 올바른 애니메이션 디스패처를 호출하는 것입니다.
아래처럼 어댑터를 확장하십시오.
public class RankingAdapter extends AnimatedRecyclerView<RankingAdapter.ViewHolder>
그리고 onBindViewHolder에 슈퍼 메소드 추가
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
super.onBindViewHolder(holder, position);
"Basheer AL-MOMANI"와 같은 애니메이션 어댑터를 만드는 자동화 된 방법
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.ScaleAnimation;
import java.util.Random;
/**
* Created by eliaszkubala on 24.02.2017.
*/
public class AnimatedRecyclerView<T extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<T> {
@Override
public T onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}
@Override
public void onBindViewHolder(T holder, int position) {
setAnimation(holder.itemView, position);
}
@Override
public int getItemCount() {
return 0;
}
protected int mLastPosition = -1;
protected void setAnimation(View viewToAnimate, int position) {
if (position > mLastPosition) {
ScaleAnimation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
anim.setDuration(new Random().nextInt(501));//to make duration random number between [0,501)
viewToAnimate.startAnimation(anim);
mLastPosition = position;
}
}
}