RecyclerView 확장 / 축소 항목


145

더 많은 정보를 표시하기 위해 recyclerView의 항목을 확장 / 축소하고 싶습니다. SlideExpandableListView 와 동일한 효과를 얻고 싶습니다 .

기본적으로 내 viewHolder에는 보이지 않는 뷰가 있으며 가시성을 VISIBLE / GONE으로 설정하는 대신 부드러운 확장 / 축소 애니메이션을하고 싶습니다. 한 번에 항목을 확장해야하며 항목이 선택되었음을 보여주기 위해 고도를 높이는 것이 좋습니다.

새로운 Android 최근 통화 내역 목록과 동일한 효과입니다. "CALL BACK"및 "DETAILS"옵션은 항목을 선택한 경우에만 표시됩니다.

RecyclerView 확장 가능 항목


관련 질문이 있습니다. 시계 앱에서 알람 설정 활동은 비슷한 기능을 가지고 있습니다. 같은 방식으로 이루어 집니까?
user2731584

이봐 해결책이 있니? 나는 또한 내 응용 프로그램에 대해 동일한 솔루션을 찾고 있습니다.
Arpit Patel

해결책을 찾았습니까?
Armin Ghoreishi

1
Google I / O 2016에 따라 권장되는 방법을 업데이트했습니다. 내 답변보기 stackoverflow.com/questions/27203817/…
Heisenberg

여기에 간단하고 멋진 솔루션으로 답을 확인하십시오. stackoverflow.com/a/48092441/5962715
Kiran Benny Joseph

답변:


192

이 효과에 라이브러리를 사용하지 말고 Google I / O에 따라 권장되는 방법을 사용하십시오. recyclerView의 onBindViewHolder 메소드에서 다음을 수행하십시오.

final boolean isExpanded = position==mExpandedPosition;
holder.details.setVisibility(isExpanded?View.VISIBLE:View.GONE);
holder.itemView.setActivated(isExpanded);
holder.itemView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        mExpandedPosition = isExpanded ? -1:position;
        TransitionManager.beginDelayedTransition(recyclerView);
        notifyDataSetChanged();
    }
});
  • 어디 세부 사항은 터치에 표시됩니다 내도이다 (귀하의 경우 통화 세부 정보가. Visibility.GONE 기본).
  • mExpandedPosition 은 -1로 초기화 된 int 변수입니다.

원하는 멋진 효과를 얻으려면 list_item 속성으로 사용하십시오.

android:background="@drawable/comment_background"
android:stateListAnimator="@animator/comment_selection"

comment_background는 다음과 같습니다.

<selector
xmlns:android="http://schemas.android.com/apk/res/android"
android:constantSize="true"
android:enterFadeDuration="@android:integer/config_shortAnimTime"
android:exitFadeDuration="@android:integer/config_shortAnimTime">

<item android:state_activated="true" android:drawable="@color/selected_comment_background" />
<item android:drawable="@color/comment_background" />
</selector>

comment_selection은 다음과 같습니다.

<selector xmlns:android="http://schemas.android.com/apk/res/android">

<item android:state_activated="true">
    <objectAnimator
        android:propertyName="translationZ"
        android:valueTo="@dimen/z_card"
        android:duration="2000"
        android:interpolator="@android:interpolator/fast_out_slow_in" />
</item>

<item>
    <objectAnimator
        android:propertyName="translationZ"
        android:valueTo="0dp"
        android:duration="2000"
        android:interpolator="@android:interpolator/fast_out_slow_in" />
</item>
</selector>

22
이 코드를 사용하면 확장 애니메이션이 이상하게 보입니다. 맨 위 항목이 사라지고 모든 것이 한 위치 위로 이동합니다. 비슷한 것을 경험 한 적이 있습니까?
chris-pollux

6
애니메이션을 시도하지만 어댑터에서이를 구현하지만 TransitionManager.beginDelayedTransition(recyclerView);재활용 뷰보기를 방해 할 수없는 경우 해결책은 무엇입니까 ?
Martín Serrano

2
@ Ranveer 그것은 일종의 작동합니다. 나는 매우 유사한 recyclerViews를 가지고 있지만 하나만 올바르게 작동합니다. 왜 그런지 모르겠다. @ MartínDaniel recyclerView어댑터 생성자에서 매개 변수로 를 전달해야합니다.
chris-pollux

26
이것은 끔찍한 접근법입니다. Google I / O에서 권장되었다고 믿을 수 없습니다. Plaid 프로젝트를 조사하고 필요한 모든 해결 방법을 구현 한 후에도 애니메이션으로 인해 RecyclerView에 몇 가지 주요 결함이 발생합니다 (예 : 첫 번째 / 마지막 표시 항목이 조기에 사라짐). 또한 애니메이션이 실행되는 동안 스크롤하면 모든 것이 잘못됩니다. 일반적으로, 나는이 접근법에 의해 야기 된 모든 문제를 고치는 것을 광고 된대로 "한 줄만 넣으면 모든 것이 작동 할 것"이라고 생각하지 않습니다.
Vitali Olshevski

6
2019 년에이 문제에 대해 더 신선하고 쉬운 방법이 있습니까?
Ponomarenko Oleh

76

이를 위해 복잡하지 않은 간단한 줄만 있으면됩니다.

onBindViewHolder 메소드에서 아래 코드를 추가하십시오.

final boolean isExpanded = position==mExpandedPosition;
holder.details.setVisibility(isExpanded?View.VISIBLE:View.GONE);
holder.itemView.setActivated(isExpanded);
holder.itemView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        mExpandedPosition = isExpanded ? -1:position;
        notifyItemChanged(position);
    }
});

mExpandedPosition 은 -1로 초기화 된 int 전역 변수입니다.

하나의 항목 만 확장하고 다른 항목은 축소하려는 경우. 이것을 사용하십시오

먼저 previousExpandedPosition = -1로 전역 변수를 선언하십시오.

그때

    final boolean isExpanded = position==mExpandedPosition;
    holder.details.setVisibility(isExpanded?View.VISIBLE:View.GONE);
    holder.itemView.setActivated(isExpanded);

    if (isExpanded)
       previousExpandedPosition = position;

    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mExpandedPosition = isExpanded ? -1:position;
            notifyItemChanged(previousExpandedPosition);
            notifyItemChanged(position);
        }
    });

끝난!!!. 간단하고 겸손한 .. :)


훌륭한 솔루션. 또한 설정 대신 OnClickListeners를onCreateViewHolderonBindViewHolder
YTerle

1
시간이 지나면 RecyclerView작업을 수행 할 수있는 적절한 솔루션이 있었 LayoutManager으므로 레이아웃을 관리하지 않으면 그렇지 않은 점이 무엇 입니까? 이 솔루션은 코드가 적고 RecyclerView처리가 가능하며 더 잘 작동 하므로 최고의 투표 솔루션 보다 낫습니다!
Mark Keen

1
"세부 사항"보기를 추가하는 방법을 이해하지 못했습니다. 각 홀더마다 정적인가? 각 목록 항목마다 다른보기를 추가해야하는 경우 어떻게합니까?
BekaBot

@BekaBot 그것은 당신이 항목을 축소하는 동안 숨기고 싶은보기입니다
Kiran Benny Joseph

@KiranBennyJoseph 예, 이해합니다. 이 경우 모든 항목에 대해보기가 동일해야합니까? 항목마다 다른보기를 원하면 어떻게합니까?
BekaBot

72

이것이 최선의 접근 방법이라고 말하지는 않지만 나에게 효과가있는 것 같습니다.

전체 코드는 다음에서 찾을 수 있습니다. 예제 코드 : https://github.com/dbleicher/recyclerview-grid-quickreturn

먼저 셀 / 항목 레이아웃에 확장 영역을 추가하고 둘러싸는 셀 레이아웃을 animateLayoutChanges = "true"로 만듭니다. 이렇게하면 확장 / 축소 애니메이션이 적용됩니다.

<LinearLayout
    android:id="@+id/llCardBack"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/white"
    android:animateLayoutChanges="true"
    android:padding="4dp"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center|fill_horizontal"
        android:padding="10dp"
        android:gravity="center"
        android:background="@android:color/holo_green_dark"
        android:text="This is a long title to show wrapping of text in the view."
        android:textColor="@android:color/white"
        android:textSize="16sp" />

    <TextView
        android:id="@+id/tvSubTitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center|fill_horizontal"
        android:background="@android:color/holo_purple"
        android:padding="6dp"
        android:text="My subtitle..."
        android:textColor="@android:color/white"
        android:textSize="12sp" />

    <LinearLayout
        android:id="@+id/llExpandArea"
        android:visibility="gone"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="6dp"
            android:text="Item One" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="6dp"
            android:text="Item Two" />

    </LinearLayout>
</LinearLayout>

그런 다음 클릭하는 항목에 대해 조치를 취할 수 있도록 RV 어댑터 클래스가 View.OnClickListener를 구현하도록하십시오. 하나의 확장 된보기의 위치를 ​​유지하기 위해 int 필드를 추가하고 음수 값으로 초기화하십시오.

private int expandedPosition = -1;

마지막으로 ViewHolder, onBindViewHolder () 메소드를 구현하고 onClick () 메소드를 대체하십시오. 위치가 "expandedPosition"과 같으면 onBindViewHolder에서보기를 확장하고 그렇지 않으면 숨 깁니다. onClick 리스너에서 extendedPosition의 값을 설정합니다.

@Override
public void onBindViewHolder(RVAdapter.ViewHolder holder, int position) {

    int colorIndex = randy.nextInt(bgColors.length);
    holder.tvTitle.setText(mDataset.get(position));
    holder.tvTitle.setBackgroundColor(bgColors[colorIndex]);
    holder.tvSubTitle.setBackgroundColor(sbgColors[colorIndex]);

    if (position == expandedPosition) {
        holder.llExpandArea.setVisibility(View.VISIBLE);
    } else {
        holder.llExpandArea.setVisibility(View.GONE);
    }
}

@Override
public void onClick(View view) {
    ViewHolder holder = (ViewHolder) view.getTag();
    String theString = mDataset.get(holder.getPosition());

    // Check for an expanded view, collapse if you find one
    if (expandedPosition >= 0) {
        int prev = expandedPosition;
        notifyItemChanged(prev);
    }
    // Set the current position to "expanded"
    expandedPosition = holder.getPosition();
    notifyItemChanged(expandedPosition);

    Toast.makeText(mContext, "Clicked: "+theString, Toast.LENGTH_SHORT).show();
}

/**
 * Create a ViewHolder to represent your cell layout
 * and data element structure
 */
public static class ViewHolder extends RecyclerView.ViewHolder {
    TextView tvTitle;
    TextView tvSubTitle;
    LinearLayout llExpandArea;

    public ViewHolder(View itemView) {
        super(itemView);

        tvTitle = (TextView) itemView.findViewById(R.id.tvTitle);
        tvSubTitle = (TextView) itemView.findViewById(R.id.tvSubTitle);
        llExpandArea = (LinearLayout) itemView.findViewById(R.id.llExpandArea);
    }
}

레이아웃 변경에 시스템 기본 애니메이션을 사용하여 한 번에 하나의 항목 만 확장해야합니다. 적어도 그것은 나를 위해 작동합니다. 도움이 되길 바랍니다.


하나의 항목 만 선택하는 방법을 알고 있습니다. 해당 항목에서 애니메이션을 수행하는 방법을 모르겠습니다. 기본 시스템 애니메이션이 포함 된 확장 / 축소 애니메이션이 매끄럽게 보이지 않습니다.
stanete

1
아직 다음을 시도하지 않았지만 제대로 작동하는 것 같습니다. stackoverflow.com/a/26443762/2259418
MojoTosh

2
@ user2731584-나는 그렇게 생각하지 않습니다. 소스를 (내가 믿는 것)봤을 때, Lollipop 시계가 ListView를 사용하여 알람 목록을 표시하는 것으로 보입니다. 레이아웃 : android.googlesource.com/platform/packages/apps/DeskClock/+/… 이 목록의 확장 / 축소 항목에 애니메이션을 적용하기위한 맞춤 코드가있는 것 같습니다. 다음 소스를 참조하십시오 : android.googlesource.com/platform/packages/apps/DeskClock/+/…
MojoTosh

1
@MojoTosh 당신이 맞아요. 그들은 ListView를 사용하고 코드를 사용하여 애니메이션을 수행하고 있습니다. 파일의 expandAlarm함수 AlarmClockFragment.java는 확장 부분을 실행합니다.
user2731584

4
어느 onClick()것을 무시해야합니까? onClick어댑터 에는 없습니다 .
Vicky Leong

15

https://github.com/cachapa/ExpandableLayout 과 같이 gradle을 지원하는 매우 사용하기 쉬운 라이브러리가 있습니다 .

도서관 문서에서 바로 :

<net.cachapa.expandablelayout.ExpandableLinearLayout
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:el_duration="1000"
    app:el_expanded="true">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Click here to toggle expansion" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:text="Fixed height"
        app:layout_expandable="true" />

 </net.cachapa.expandablelayout.ExpandableLinearLayout>

당신이 당신의 표시 후 확장 전망을 단지 용기에 이러한 방법을 호출 expand(), collapse()또는toggle()


이것이 여전히 최선의 방법입니까? 나는 당신이 쓴 것을 따르려고 노력하고 있습니다. 클릭하면 그래프를 표시하기 위해 확장하고 싶은 재활용보기가 있습니다.
sourlemonaid

10

원래 질문이 게시 된 이후 오랜 시간이 걸렸다는 것을 알고 있습니다. 그러나 나는 나와 같은 느린 사람들에게는 @Heisenberg의 대답에 대한 약간의 설명이 도움이 될 것이라고 생각합니다.

어댑터 클래스에서 두 개의 변수를 다음과 같이 선언하십시오.

private int mExpandedPosition= -1;
private RecyclerView recyclerView = null;

그런 다음 원래 답변에서 주어진대로 onBindViewHolder 에서.

      // This line checks if the item displayed on screen 
      // was expanded or not (Remembering the fact that Recycler View )
      // reuses views so onBindViewHolder will be called for all
      // items visible on screen.
    final boolean isExpanded = position==mExpandedPosition;

        //This line hides or shows the layout in question
        holder.details.setVisibility(isExpanded?View.VISIBLE:View.GONE);

        // I do not know what the heck this is :)
        holder.itemView.setActivated(isExpanded);

        // Click event for each item (itemView is an in-built variable of holder class)
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

 // if the clicked item is already expaned then return -1 
//else return the position (this works with notifyDatasetchanged )
                mExpandedPosition = isExpanded ? -1:position;
    // fancy animations can skip if like
                TransitionManager.beginDelayedTransition(recyclerView);
    //This will call the onBindViewHolder for all the itemViews on Screen
                notifyDataSetChanged();
            }
        });

마지막으로 어댑터 재정의에서 recyclerView 객체를 얻으려면

@Override
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
    super.onAttachedToRecyclerView(recyclerView);

    this.recyclerView = recyclerView;
}

도움이 되었기를 바랍니다.


3
위대하고 간단한 해결책. 약간의 개선은 매직 넘버 -1 대신 RecyclerView.NO_POSITION을 사용하십시오.
Casper Bang

8

타사 라이브러리를 사용할 필요가 없습니다. 약간의 비틀기 에서 설명하는 방법에 구글 I / O 2016 이 주제에와 하이젠 베르크는 트릭을 수행합니다.

이후 notifyDataSetChanged() 전체 다시 그리기RecyclerView , notifyDataItemChanged()우리는 위치와 있기 때문에 더 나은 옵션 (안 최고)입니다 ViewHolder우리의 처분을하고, notifyDataItemChanged()단지 특정을 다시 그립니다 ViewHolder주어진 위치에서 .

그러나 문제는 ViewHolder클릭시 조기 소멸 과 출현 notifyDataItemChanged()이 사용 되어도 제거되지 않는다는 것 입니다.

다음 코드는 하지 않습니다 에 의존 notifyDataSetChanged()하거나 notifyDataItemChanged()각 ViewHolder이가있는 RecyclerView에 사용하는 경우 API (23)와 마법처럼 작품에서 테스트되고 CardView그것의 루트 요소로 :

holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            final boolean visibility = holder.details.getVisibility()==View.VISIBLE;

            if (!visibility)
            {
                holder.itemView.setActivated(true);
                holder.details.setVisibility(View.VISIBLE);
                if (prev_expanded!=-1 && prev_expanded!=position)
                {
                    recycler.findViewHolderForLayoutPosition(prev_expanded).itemView.setActivated(false);
                    recycler.findViewHolderForLayoutPosition(prev_expanded).itemView.findViewById(R.id.cpl_details).setVisibility(View.GONE);
                }
                prev_expanded = position;
            }
            else
            {
                holder.itemView.setActivated(false);
                holder.details.setVisibility(View.GONE);
            }
            TransitionManager.beginDelayedTransition(recycler);              
        }
});

prev_position-1로 초기화 된 전역 정수입니다. details접었을 때 펼치고 닫힐 때 표시되는 전체보기입니다.

앞서 언급했듯이의 루트 요소 ViewHolderCardViewwith foregroundstateListAnimator특성에 대해 Heisenberg가 말한대로 정확하게 정의됩니다.

업데이트 : 위의 데모는 확장 된 항목 중 하나가 확장 된 경우 이전에 확장 된 항목을 축소합니다. 이 동작을 수정하고 확장 된 항목을 다른 항목이 확장 된 경우에도 그대로 유지하려면 다음 코드가 필요합니다.

if (row.details.getVisibility()!=View.VISIBLE)
    {
        row.details.setVisibility(View.VISIBLE);
        row.root.setActivated(true);
        row.details.animate().alpha(1).setStartDelay(500);
    }
    else
    {
        row.root.setActivated(false);
        row.details.setVisibility(View.GONE);
        row.details.setAlpha(0);
    }
    TransitionManager.beginDelayedTransition(recycler);

업데이트 : 목록의 마지막 항목을 펼칠 때 펼친 부분이 화면 아래로 이동하기 때문에 완전히 표시되지 않을 수 있습니다. 화면 내에서 전체 항목을 얻으려면 다음 코드를 사용하십시오.

LinearLayoutManager manager = (LinearLayoutManager) recycler.getLayoutManager();
    int distance;
    View first = recycler.getChildAt(0);
    int height = first.getHeight();
    int current = recycler.getChildAdapterPosition(first);
    int p = Math.abs(position - current);
    if (p > 5) distance = (p - (p - 5)) * height;
    else       distance = p * height;
    manager.scrollToPositionWithOffset(position, distance);

중요 : 위의 데모가 작동하려면 코드에서 RecyclerView의 인스턴스를 유지해야하며 LayoutManager는 유연성이 있어야합니다.


이 솔루션이 저에게 효과적입니다. URL에서 어떤로드 이미지 notifyItemChanged가 있기 때문에 사용을 피하려고합니다 ImageView. notifyItemChanged내 이미지를
새로

손톱을 깎는 선은 TransitionManager.beginDelayedTransition(recycler);훌륭합니다. 그러나이 방법을 사용하여 여러 행을 순차적으로 스팸 클릭하면 결국 내부 충돌이 발생한다는 것을 알았습니다 The specified child already has a parent. You must call removeView() on the child's parent first. 이것이 재활용 뷰 경계에서 뷰 재활용으로 인한 것이라고 생각하지만 확실하게 말할 수는 없습니다. 누구 같은 문제가 있었나요?
Roger Oba

이것이 여전히 최선의 방법입니까? 나는 당신이 쓴 것을 따르려고 노력하고 있습니다. 클릭 할 때 그래프를 표시하기 위해 확장하려는 재활용보기가 있습니다. 내가 할 정확히 이해 힘든 시간을 보내고 있어요
sourlemonaid

누구 든지이 구현의 완전한 예를 가지고 있습니까? 작동 코드 예제를 의미합니다. 도와주세요. 어떻게하는지 이해할 수 없습니까?
Munazza

7

A의 거주 확장 / 축소 항목을 구현하는 권장되는 방법 사용 후 RecyclerViewRecyclerView이 / 축소 항목 확장 응답 하이젠 베르크를 , 나는이 때마다 몇 가지 눈에 띄는 유물 본 적이 RecyclerView호출하여 새로 고쳐 TransitionManager.beginDelayedTransition(ViewGroup)과 이후를 notifyDatasetChanged().

그의 원래 답변 :

final boolean isExpanded = position==mExpandedPosition;
holder.details.setVisibility(isExpanded?View.VISIBLE:View.GONE);
holder.itemView.setActivated(isExpanded);
holder.itemView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        mExpandedPosition = isExpanded ? -1 : position;
        TransitionManager.beginDelayedTransition(recyclerView);
        notifyDataSetChanged();
    }
});

수정 :

final boolean isExpanded = position == mExpandedPosition;
holder.details.setVisibility(isExpanded ? View.VISIBLE : View.GONE);
holder.view.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (mExpandedHolder != null) {
            mExpandedHolder.details.setVisibility(View.GONE);
            notifyItemChanged(mExpandedPosition);
        }
        mExpandedPosition = isExpanded ? -1 : holder.getAdapterPosition();
        mExpandedHolder = isExpanded ? null : holder;
        notifyItemChanged(holder.getAdapterPosition());
    }
}
  • 세부 사항 은 항목 확장 / 축소 중에 표시하거나 숨기려는보기입니다.
  • mExpandedPositionint확장 된 항목을 추적하는
  • mExpandedHolderViewHolder항목 축소 중에 사용됩니다

특정 항목과 약간의 미세 조정을 대상 으로 하기 위해이 방법 TransitionManager.beginDelayedTransition(ViewGroup)과 방법 notifyDataSetChanged()이 대체되었습니다 notifyItemChanged(int).

수정 후에는 이전에 원하지 않는 효과가 사라져야합니다. 그러나 이것은 완벽한 솔루션이 아닐 수 있습니다. 그것은 내가 원하는 것을 했으므로 눈가리개를 제거했습니다.

::편집하다::

설명을 위해, 모두 mExpandedPositionmExpandedHolder전역이다.


mExpandedHolder가 어떻게 그리고 어디에서 선언되고 사용되는지 설명해주세요.
베르너

1
@Werner 나는 답변이 어디에 선언되었는지 표시하도록 편집했다. 사용법은 스 니펫 자체와 목적 내에 있습니다. 접 히고 확장 된 항목을 애니메이션하는 데 사용됩니다.
Chan Teck Wei

애니메이션에 관한 한이 방법을 가장 좋아하지만 항목을 클릭 할 때이 "페이드"가 작습니다. notifyItemChanged ()를 사용하기 때문입니까? drive.google.com/file/d/1GaU1fcjHEfSErYF50otQGLGsIWkSyQSe/…
kazume

예. 당신이 짐작했듯이,에 의해 발생합니다 notifyItemChanged(). 항목 높이를 수동으로 애니메이션 및 변경하고보기를 추가 할 수 있습니다.
Chan Teck Wei

@ ChanTeckWei : 귀하의 솔루션은 잘 작동하지만 recyclerview 항목 행을 축소하거나 확장 할 때마다 행 이미지가 깜박입니다.
Pragya Mendiratta

3

onClick 리스너를 ViewHolder 클래스로 설정 한 후 다음을 수행하십시오.

@Override
    public void onClick(View v) {
        final int originalHeight = yourLinearLayout.getHeight();
        animationDown(YourLinearLayout, originalHeight);//here put the name of you layout that have the options to expand.
    }

    //Animation for devices with kitkat and below
    public void animationDown(LinearLayout billChoices, int originalHeight){

        // Declare a ValueAnimator object
        ValueAnimator valueAnimator;
        if (!billChoices.isShown()) {
            billChoices.setVisibility(View.VISIBLE);
            billChoices.setEnabled(true);
            valueAnimator = ValueAnimator.ofInt(0, originalHeight+originalHeight); // These values in this method can be changed to expand however much you like
        } else {
            valueAnimator = ValueAnimator.ofInt(originalHeight+originalHeight, 0);

            Animation a = new AlphaAnimation(1.00f, 0.00f); // Fade out

            a.setDuration(200);
            // Set a listener to the animation and configure onAnimationEnd
            a.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {

                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    billChoices.setVisibility(View.INVISIBLE);
                    billChoices.setEnabled(false);
                }

                @Override
                public void onAnimationRepeat(Animation animation) {

                }
            });
            // Set the animation on the custom view
            billChoices.startAnimation(a);
        }
        valueAnimator.setDuration(200);
        valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            public void onAnimationUpdate(ValueAnimator animation) {
                Integer value = (Integer) animation.getAnimatedValue();
                billChoices.getLayoutParams().height = value.intValue();
                billChoices.requestLayout();
            }
        });


        valueAnimator.start();
    }
}

나는 그것이 도움이 될 것이라고 생각한다. 그것이 내가 최근 통화보기에서 구현 한 구글과 동일한 방식이다.


2

간결한 답변이 아직 없다는 사실에 놀랐습니다. 그러나 이러한 확장 / 축소 애니메이션은 단 두 줄의 코드로 달성하기가 매우 쉽습니다.

(recycler.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false // called once

함께

notifyItemChanged(position) // in adapter, whenever a child view in item's recycler gets hidden/shown

그래서 저에게 아래 링크의 설명은 정말 유용했습니다 : https://medium.com/@nikola.jakshic/how-to-expand-collapse-items-in-recyclerview-49a648a403a6


1
//Global Variable

private int selectedPosition = -1;

 @Override
    public void onBindViewHolder(final CustomViewHolder customViewHolder, final int i) {

        final int position = i;
        final GetProductCatalouge.details feedItem = this.postBeanses.get(i);
        customViewHolder.lly_main.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                selectedPosition = i;
                notifyDataSetChanged();
            }
        });
        if (selectedPosition == i) {

          if (customViewHolder.lly_hsn_code.getVisibility() == View.VISIBLE) {

            customViewHolder.lly_hsn_code.setVisibility(View.GONE);
            customViewHolder.lly_sole.setVisibility(View.GONE);
            customViewHolder.lly_sole_material.setVisibility(View.GONE);

        } else {

            customViewHolder.lly_hsn_code.setVisibility(View.VISIBLE);
            customViewHolder.lly_sole.setVisibility(View.VISIBLE);
            customViewHolder.lly_sole_material.setVisibility(View.VISIBLE);
        }


        } else {
            customViewHolder.lly_hsn_code.setVisibility(View.GONE);
            customViewHolder.lly_sole.setVisibility(View.GONE);
            customViewHolder.lly_sole_material.setVisibility(View.GONE);
        }
}

여기에 이미지 설명을 입력하십시오


0

에 두 가지보기 유형을 사용하십시오 RVAdapter. 하나는 확장 된 레이아웃이고 다른 하나는 축소 된 것입니다. 이 비디오 에서 0:42에 이것을 사용하여 달성 한 효과 android:animateLayoutChanges="true"RecyclerViewCheckout 으로 설정하면 마술이 발생합니다.


이것을 더 잘 설명해 주시겠습니까? 나는 그것을 작동시킬 수 없다
sourlemonaid

@sourlemonaid는 기본적으로 stackoverflow.com/a/26245463/3731795에 설명 된대로 목록에 대해 여러보기 유형을 만듭니다 ... 항목이 확장 된 색인 추적을 유지하고 그 때 나머지 항목은 축소됩니다 . 이제 if (current_item_index == extended_item_index) {return VIEW_TYPE_EXPANDED} else {reutrn VIEW_TYPE_COLLAPSED}
penduDev
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.