RecyclerView.State를 사용하여 RecyclerView의 스크롤 위치를 저장하는 방법은 무엇입니까?


107

Android의 RecyclerView.State 에 대한 질문이 있습니다 .

RecyclerView를 사용하고 있는데 RecyclerView.State와 어떻게 사용하고 바인딩 할 수 있습니까?

내 목적은 RecyclerView의 스크롤 위치저장하는 것입니다 .

답변:


37

마지막으로 저장된 위치를 RecyclerView.State어떻게 저장할 계획 입니까?

항상 좋은 저장 상태에 의존 할 수 있습니다. RecyclerViewonSaveInstanceState ()를 확장 하고 재정의합니다 onRestoreInstanceState().

    @Override
    protected Parcelable onSaveInstanceState() {
        Parcelable superState = super.onSaveInstanceState();
        LayoutManager layoutManager = getLayoutManager();
        if(layoutManager != null && layoutManager instanceof LinearLayoutManager){
            mScrollPosition = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
        }
        SavedState newState = new SavedState(superState);
        newState.mScrollPosition = mScrollPosition;
        return newState;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        super.onRestoreInstanceState(state);
        if(state != null && state instanceof SavedState){
            mScrollPosition = ((SavedState) state).mScrollPosition;
            LayoutManager layoutManager = getLayoutManager();
            if(layoutManager != null){
              int count = layoutManager.getItemCount();
              if(mScrollPosition != RecyclerView.NO_POSITION && mScrollPosition < count){
                  layoutManager.scrollToPosition(mScrollPosition);
              }
            }
        }
    }

    static class SavedState extends android.view.View.BaseSavedState {
        public int mScrollPosition;
        SavedState(Parcel in) {
            super(in);
            mScrollPosition = in.readInt();
        }
        SavedState(Parcelable superState) {
            super(superState);
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            super.writeToParcel(dest, flags);
            dest.writeInt(mScrollPosition);
        }
        public static final Parcelable.Creator<SavedState> CREATOR
                = new Parcelable.Creator<SavedState>() {
            @Override
            public SavedState createFromParcel(Parcel in) {
                return new SavedState(in);
            }

            @Override
            public SavedState[] newArray(int size) {
                return new SavedState[size];
            }
        };
    }

1
이제 RecyclerView.State가 무엇을 할 수 있는지에 대한 또 다른 질문이 있습니다.
陈文涛

4
정말 효과가 있나요? 나는 이것을 시도했다, 그러나 나는이 같은 런타임 예외가 계속 : MyRecyclerView $ SavedState는 android.support.v7.widget.RecyclerView $ SavedState 캐스트 할 수없는
Daivid

2
복원 인스턴스 상태에서 다음과 같이 superState를 수퍼 클래스 (재활용보기)에 전달해야합니다. super.onRestoreInstanceState (((ScrollPositionSavingRecyclerView.SavedState) state) .getSuperState ());
micnoy

5
RecyclerView를 확장하면 작동하지 않으며 BadParcelException이 발생합니다.
EpicPandaForce 2015 년

1
이 중 아무것도 필요하지 않습니다. LinearLayoutManager / GridLayoutManager와 같은 것을 사용하는 경우 "스크롤 위치"가 이미 자동으로 저장됩니다. (LinearLayoutManager.SavedState의 mAnchorPosition입니다). 이것이 보이지 않는다면 데이터를 다시 적용하는 방법에 문제가있는 것입니다.
Brian Yencho

229

최신 정보

recyclerview:1.2.0-alpha02출시 부터 StateRestorationPolicy도입되었습니다. 주어진 문제에 대한 더 나은 접근 방식이 될 수 있습니다.

이 주제는 안드로이드 개발자 중간 기사 에서 다루었습니다 .

또한 @ rubén-viguera는 아래 답변에서 자세한 내용을 공유했습니다. https://stackoverflow.com/a/61609823/892500

이전 답변

LinearLayoutManager를 사용하는 경우 미리 빌드 된 저장 API linearLayoutManagerInstance.onSaveInstanceState () 및 복원 api linearLayoutManagerInstance.onRestoreInstanceState (...)가 함께 제공됩니다.

이를 통해 반환 된 parcelable을 outState에 저장할 수 있습니다. 예 :

outState.putParcelable("KeyForLayoutManagerState", linearLayoutManagerInstance.onSaveInstanceState());

, 저장 한 상태로 복원 위치를 복원합니다. 예 :

Parcelable state = savedInstanceState.getParcelable("KeyForLayoutManagerState");
linearLayoutManagerInstance.onRestoreInstanceState(state);

모두 마무리하면 최종 코드는 다음과 같습니다.

private static final String BUNDLE_RECYCLER_LAYOUT = "classname.recycler.layout";

/**
 * This is a method for Fragment. 
 * You can do the same in onCreate or onRestoreInstanceState
 */
@Override
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
    super.onViewStateRestored(savedInstanceState);

    if(savedInstanceState != null)
    {
        Parcelable savedRecyclerLayoutState = savedInstanceState.getParcelable(BUNDLE_RECYCLER_LAYOUT);
        recyclerView.getLayoutManager().onRestoreInstanceState(savedRecyclerLayoutState);
    }
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putParcelable(BUNDLE_RECYCLER_LAYOUT, recyclerView.getLayoutManager().onSaveInstanceState());
}

편집 : LinearLayoutManager의 하위 클래스이기 때문에 GridLayoutManager와 동일한 api를 사용할 수도 있습니다. 제안에 대해 @wegsehen에게 감사드립니다.

편집 : 백그라운드 스레드에서도 데이터를로드하는 경우 방향 변경시 위치를 복원하려면 onPostExecute / onLoadFinished 메서드 내에서 onRestoreInstanceState를 호출해야합니다. 예 :

@Override
protected void onPostExecute(ArrayList<Movie> movies) {
    mLoadingIndicator.setVisibility(View.INVISIBLE);
    if (movies != null) {
        showMoviePosterDataView();
        mDataAdapter.setMovies(movies);
      mRecyclerView.getLayoutManager().onRestoreInstanceState(mSavedRecyclerLayoutState);
        } else {
            showErrorMessage();
        }
    }

21
이것은 분명히 최선의 대답입니다. 왜 이것이 허용되지 않습니까? 모든 LayoutManager에는 LinearLayoutManager뿐만 아니라 GridLayoutManager도 있으며, 그렇지 않은 경우 false 구현이 있습니다.
Paul Woitaschek

linearLayoutManager.onInstanceState ()는 항상 null을 반환합니다-> 소스 코드를 확인합니다. 불행히도 작동하지 않습니다.
luckyhandler

1
RecyclerView는 자체 onSaveInstanceState에 LayoutManager의 상태를 저장하지 않습니까? ... 지원 LIB의 V24을 보면
androidguy

3
이는 단일 작동 RecyclerView하지만 당신은이없는 경우 ViewPagerA를을 RecycerView각 페이지에.
Kris B

1
@Ivan, 나는 그것이 조각 (방금 확인)에서 작동한다고 생각하지만에서는 작동하지 onCreateView않지만 데이터로드 후에는 작동합니다. 여기에서 @Farmaker 답변을 참조하십시오.
CoolMind

81

저장

lastFirstVisiblePosition = ((LinearLayoutManager)rv.getLayoutManager()).findFirstCompletelyVisibleItemPosition();

복원

((LinearLayoutManager) rv.getLayoutManager()).scrollToPosition(lastFirstVisiblePosition);

그래도 작동하지 않으면

((LinearLayoutManager) rv.getLayoutManager()).scrollToPositionWithOffset(lastFirstVisiblePosition,0)

저장 onPause() 및 복원onResume()


이것은 작동하지만, 당신은을 재설정해야 할 수도 있습니다 lastFirstVisiblePosition0그것을 복원 한 후. 이 사례는 RecyclerView파일 탐색기 앱과 같이 하나에 다른 데이터를로드하는 조각 / 활동이있는 경우에 유용 합니다.
blueware

우수한! 세부 활동에서 목록으로 돌아가는 것과 화면 회전시 상태 저장 모두를 충족합니다
Javi

내 recyclerView가 있으면 어떻게해야합니까 SwipeRefreshLayout?
Morozov

2
첫 번째 복원 옵션이 작동하지 않고 두 번째 옵션이 작동하는 이유는 무엇입니까?
lucidbrot

1
@MehranJalili 그것은 것 같습니다RecyclerView
Vlad

22

내 목록 활동에서 멀리 이동할 때 Recycler View의 스크롤 위치를 저장하고 뒤로 이동하기 위해 뒤로 버튼을 클릭하고 싶었습니다. 이 문제에 대해 제공된 많은 솔루션이 필요 이상으로 복잡하거나 내 구성에서 작동하지 않으므로 솔루션을 공유 할 것이라고 생각했습니다.

먼저 많은 사람들이 보여준대로 onPause에 인스턴스 상태를 저장합니다. 이 버전의 onSaveInstanceState가 RecyclerView.LayoutManager 클래스의 메서드라는 점을 여기서 강조 할 가치가 있다고 생각합니다.

private LinearLayoutManager mLayoutManager;
Parcelable state;

        @Override
        public void onPause() {
            super.onPause();
            state = mLayoutManager.onSaveInstanceState();
        }

이것이 제대로 작동하도록하는 핵심은 어댑터를 연결 한 후 onRestoreInstanceState를 호출하는 것입니다. 일부는 다른 스레드에 표시되어 있습니다. 그러나 실제 메서드 호출은 많은 사람들이 표시 한 것보다 훨씬 간단합니다.

private void someMethod() {
    mVenueRecyclerView.setAdapter(mVenueAdapter);
    mLayoutManager.onRestoreInstanceState(state);
}

1
그것이 정확한 해결책입니다. : D
Afjalur 라만라나

1
나를 위해 onSaveInstanceState는 호출되지 않으므로 onPause에 상태를 저장하는 것이 더 나은 옵션처럼 보입니다. 메신저도 백 스택을 터 뜨리고 조각으로 돌아갑니다.
filthy_wizard

상태의 부하. 나는 onViewCreated에서 수행합니다. 디버그 모드에서 중단 점을 사용할 때만 작동하는 것 같습니다. 또는 지연을 추가하고 실행을 코 루틴에 넣는 경우.
filthy_wizard

21

onCreate ()에 변수를 설정하고 onPause ()에 스크롤 위치를 저장하고 onResume ()에 스크롤 위치를 설정합니다.

public static int index = -1;
public static int top = -1;
LinearLayoutManager mLayoutManager;

@Override
public void onCreate(Bundle savedInstanceState)
{
    //Set Variables
    super.onCreate(savedInstanceState);
    cRecyclerView = ( RecyclerView )findViewById(R.id.conv_recycler);
    mLayoutManager = new LinearLayoutManager(this);
    cRecyclerView.setHasFixedSize(true);
    cRecyclerView.setLayoutManager(mLayoutManager);

}

@Override
public void onPause()
{
    super.onPause();
    //read current recyclerview position
    index = mLayoutManager.findFirstVisibleItemPosition();
    View v = cRecyclerView.getChildAt(0);
    top = (v == null) ? 0 : (v.getTop() - cRecyclerView.getPaddingTop());
}

@Override
public void onResume()
{
    super.onResume();
    //set recyclerview position
    if(index != -1)
    {
        mLayoutManager.scrollToPositionWithOffset( index, top);
    }
}

항목의 오프셋도 유지하십시오. 좋은. 감사!
t0m


14

지원 라이브러리에 번들로 제공되는 모든 레이아웃 관리자는 스크롤 위치를 저장하고 복원하는 방법을 이미 알고 있습니다.

스크롤 위치는 다음 조건이 충족 될 때 발생하는 첫 번째 레이아웃 단계에서 복원됩니다.

  • 레이아웃 관리자는 RecyclerView
  • 어댑터가 RecyclerView

일반적으로 레이아웃 관리자를 XML로 설정하므로 지금해야 할 일은

  1. 데이터와 함께 어댑터로드
  2. 그런 다음 어댑터를RecyclerView

이 작업은 언제든지 수행 할 수 있으며 Fragment.onCreateView또는로 제한되지 않습니다 Activity.onCreate.

예 : 데이터가 업데이트 될 때마다 어댑터가 연결되어 있는지 확인하십시오.

viewModel.liveData.observe(this) {
    // Load adapter.
    adapter.data = it

    if (list.adapter != adapter) {
        // Only set the adapter if we didn't do it already.
        list.adapter = adapter
    }
}

저장된 스크롤 위치는 다음 데이터에서 계산됩니다.

  • 화면에서 첫 번째 항목의 어댑터 위치
  • 목록 상단에서 항목 상단의 픽셀 오프셋 (세로 레이아웃의 경우)

따라서 항목의 크기가 세로 및 가로 방향이 다른 경우 약간의 불일치를 예상 할 수 있습니다.


RecyclerView/ ScrollView/ 가질 필요가 어떤 android:id상태에 저장 될 수 있습니다.


이것은 나를위한 것이었다. 처음에는 어댑터를 설정 한 다음 사용 가능할 때 데이터를 업데이트했습니다. 위에서 설명한대로 데이터를 사용할 수있을 때까지 그대로두면 자동으로 원래 위치로 스크롤됩니다.
NeilS

감사합니다 @Eugen. LayoutManager의 스크롤 위치 저장 및 복원에 대한 문서가 있습니까?
Adam Hurwitz

@AdamHurwitz 어떤 종류의 문서를 기대하십니까? 내가 설명한 것은 LinearLayoutManager의 구현 세부 사항이므로 소스 코드를 읽으십시오.
Eugen Pechanec

1
여기에 링크가 있습니다 LinearLayoutManager.SavedState. cs.android.com/androidx/platform/frameworks/support/+/…
Eugen Pechanec

감사합니다, @EugenPechanec. 이것은 장치 회전에 효과적이었습니다. 또한 하단 탐색보기를 사용하고 있으며 다른 하단 탭으로 전환하고 돌아 오면 목록이 처음부터 다시 시작됩니다. 이것이 왜 그런지에 대한 아이디어가 있습니까?
schv09

4

여기에 그것들을 저장하고 조각에서 recyclerview의 상태를 유지하는 방법이 있습니다. 먼저 아래 코드와 같이 상위 활동에 구성 변경 사항을 추가하십시오.

android:configChanges="orientation|screenSize"

그런 다음 Fragment에서 이러한 인스턴스 메서드의

private  Bundle mBundleRecyclerViewState;
private Parcelable mListState = null;
private LinearLayoutManager mLinearLayoutManager;

@onPause 메서드에 아래 코드를 추가하십시오.

@Override
public void onPause() {
    super.onPause();
    //This used to store the state of recycler view
    mBundleRecyclerViewState = new Bundle();
    mListState =mTrailersRecyclerView.getLayoutManager().onSaveInstanceState();
    mBundleRecyclerViewState.putParcelable(getResources().getString(R.string.recycler_scroll_position_key), mListState);
}

아래와 같이 onConfigartionChanged Method를 추가합니다.

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    //When orientation is changed then grid column count is also changed so get every time
    Log.e(TAG, "onConfigurationChanged: " );
    if (mBundleRecyclerViewState != null) {
        new Handler().postDelayed(new Runnable() {

            @Override
            public void run() {
                mListState = mBundleRecyclerViewState.getParcelable(getResources().getString(R.string.recycler_scroll_position_key));
                mTrailersRecyclerView.getLayoutManager().onRestoreInstanceState(mListState);

            }
        }, 50);
    }
    mTrailersRecyclerView.setLayoutManager(mLinearLayoutManager);
}

이 접근 방식은 문제를 다시 해결할 것입니다. 다른 레이아웃 관리자가 있으면 상위 레이아웃 관리자를 교체하십시오.


데이터를 유지하기 위해 핸들러가 필요하지 않을 수 있습니다. 수명주기 방법은 저장 /로드에 충분합니다.
Mahi

@sayaMahi 적절한 방법으로 설명 할 수 있습니다. 또한 onConfigurationChanged가 destroy 메소드를 호출하지 못하도록하는 것을 보았습니다. 따라서 적절한 해결책이 아닙니다.
Pawan kumar sharma

3

AsyncTaskLoader를 사용하여 인터넷에서 데이터를 다시로드해야 할 때 회전 후 GridLayoutManager로 RecyclerView 위치를 복원하는 방법입니다.

Parcelable 및 GridLayoutManager의 전역 변수와 정적 최종 문자열을 만듭니다.

private Parcelable savedRecyclerLayoutState;
private GridLayoutManager mGridLayoutManager;
private static final String BUNDLE_RECYCLER_LAYOUT = "recycler_layout";

onSaveInstance ()에 gridLayoutManager 상태 저장

 @Override
        protected void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            outState.putParcelable(BUNDLE_RECYCLER_LAYOUT, 
            mGridLayoutManager.onSaveInstanceState());
        }

onRestoreInstanceState에서 복원

@Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);

        //restore recycler view at same position
        if (savedInstanceState != null) {
            savedRecyclerLayoutState = savedInstanceState.getParcelable(BUNDLE_RECYCLER_LAYOUT);
        }
    }

그런 다음 로더가 인터넷에서 데이터를 가져올 때 onLoadFinished ()에서 recyclerview 위치를 복원합니다.

if(savedRecyclerLayoutState!=null){
                mGridLayoutManager.onRestoreInstanceState(savedRecyclerLayoutState);
            }

.. 물론 onCreate 내에서 gridLayoutManager를 인스턴스화해야합니다. 건배


3

동일한 요구 사항이 있었지만 여기의 솔루션은 recyclerView의 데이터 소스로 인해 선을 넘지 못했습니다.

onPause ()에서 RecyclerViews의 LinearLayoutManager 상태를 추출했습니다.

private Parcelable state;

Public void onPause() {
    state = mLinearLayoutManager.onSaveInstanceState();
}

Parcelable state은에 저장되고에서 onSaveInstanceState(Bundle outState)다시 추출 onCreate(Bundle savedInstanceState)됩니다 savedInstanceState != null.

그러나 recyclerView 어댑터는 Room 데이터베이스에 대한 DAO 호출에 의해 반환 된 ViewModel LiveData 개체에 의해 채워지고 업데이트됩니다.

mViewModel.getAllDataToDisplay(mSelectedData).observe(this, new Observer<List<String>>() {
    @Override
    public void onChanged(@Nullable final List<String> displayStrings) {
        mAdapter.swapData(displayStrings);
        mLinearLayoutManager.onRestoreInstanceState(state);
    }
});

결국 어댑터에 데이터가 설정된 직후 인스턴스 상태를 복원하면 회전에 걸쳐 스크롤 상태가 유지된다는 것을 알게되었습니다.

LinearLayoutManager데이터베이스 호출에 의해 데이터가 반환 될 때 복원 한 상태를 덮어 쓰거나 복원 된 상태가 '빈'LinearLayoutManager에 대해 무의미 했기 때문 이라고 생각합니다.

어댑터 데이터를 직접 사용할 수있는 경우 (즉, 데이터베이스 호출에서 연속적이지 않은 경우), 어댑터가 recyclerView에 설정된 후에 LinearLayoutManager에서 인스턴스 상태를 복원 할 수 있습니다.

두 시나리오의 차이는 오랫동안 나를 붙 잡았습니다.


3

Android API 레벨 28에서는 제 LinearLayoutManagerRecyclerView.AdapterFragment#onCreateView방법과 Just Worked ™ ️ 모든 것을 설정했는지 확인합니다 . 나는 어떤 할 필요가 없었 onSaveInstanceState거나 onRestoreInstanceState일을.

Eugen Pechanec의 답변은 이것이 작동하는 이유를 설명합니다.


2

androidx recyclerView 라이브러리의 버전 1.2.0-alpha02부터 이제 자동으로 관리됩니다. 다음과 같이 추가하십시오.

implementation "androidx.recyclerview:recyclerview:1.2.0-alpha02"

그리고 사용 :

adapter.stateRestorationPolicy = StateRestorationPolicy.PREVENT_WHEN_EMPTY

StateRestorationPolicy 열거 형에는 3 가지 옵션이 있습니다.

  • ALLOW — 다음 레이아웃 단계에서 RecyclerView 상태를 즉시 복원하는 기본 상태
  • PREVENT_WHEN_EMPTY — 어댑터가 비어 있지 않은 경우에만 RecyclerView 상태를 복원합니다 (adapter.getItemCount ()> 0). 데이터가 비동기로로드되는 경우 RecyclerView는 데이터가로드 될 때까지 기다린 다음 상태가 복원됩니다. 어댑터의 일부로 헤더 또는로드 진행률 표시기와 같은 기본 항목이있는 경우 MergeAdapter를 사용하여 기본 항목을 추가하지 않는 한 PREVENT 옵션을 사용해야합니다 . MergeAdapter는 모든 어댑터가 준비 될 때까지 기다린 다음 상태를 복원합니다.
  • PREVENT — ALLOW 또는 PREVENT_WHEN_EMPTY를 설정할 때까지 모든 상태 복원이 지연됩니다.

이 답변 당시 recyclerView 라이브러리는 여전히 alpha03이지만 알파 단계는 프로덕션 목적에 적합하지 않습니다 .


너무 많은 과로가 절약되었습니다. 그렇지 않으면 목록 클릭 인덱스를 저장하고, 요소를 복원하고, onCreateView에서 다시 그리기를 방지하고, scrollToPosition을 적용 (또는 다른 답변으로 수행)해야했지만 사용자는 돌아온 후 차이를 알 수있었습니다
Rahul Kahale

또한 앱을 탐색 한 후 RecyclerView 위치를 저장하고 싶은 경우 ... 그에 대한 도구가 있습니까?
StayCool

@RubenViguera 알파가 프로덕션 목적이 아닌 이유는 무엇입니까? 정말 나쁜가요?
StayCool

1

나에게 문제는 어댑터를 변경할 때마다 새 레이아웃 관리자를 설정하여 recyclerView에서 스크롤 위치를 잃었다는 것입니다.


1

RecyclerView에 대한 최근의 곤경을 공유하고 싶습니다. 나는 같은 문제를 겪고있는 모든 사람이 도움이되기를 바랍니다.

내 프로젝트 요구 사항 : 그래서 내 주요 활동 (Activity-A)에서 클릭 가능한 항목을 나열하는 RecyclerView가 있습니다. 항목을 클릭하면 항목 세부 정보 (활동 -B)와 함께 새 활동이 표시됩니다.

매니페스트 파일에서 Activity-A가 Activity-B의 부모라는 것을 구현했습니다. 그런 식으로 Activity-B의 ActionBar에 뒤로 또는 홈 버튼이 있습니다.

문제 : Activity-B ActionBar에서 뒤로 또는 홈 버튼을 누를 때마다 Activity-A가 onCreate ()에서 시작하는 전체 활동 수명 주기로 들어갑니다.

RecyclerView의 어댑터 목록을 저장하는 onSaveInstanceState ()를 구현했지만 Activity-A가 수명주기를 시작할 때 onCreate () 메서드에서 saveInstanceState는 항상 null입니다.

인터넷을 더 파헤쳐 보면 동일한 문제가 발생했지만 Anroid 장치 아래의 뒤로 또는 홈 버튼 (기본 뒤로 / 홈 버튼)이 활동 A가 활동 라이프 사이클에 들어 가지 않는다는 것을 알게되었습니다.

해결책:

  1. Activity-B의 매니페스트에서 부모 활동에 대한 태그를 제거했습니다.
  2. Activity-B에서 홈 또는 뒤로 버튼을 활성화했습니다.

    onCreate () 메서드 아래에 supportActionBar? .setDisplayHomeAsUpEnabled (true) 줄을 추가합니다.

  3. overide fun onOptionsItemSelected () 메서드에서 id를 기반으로 항목을 클릭 한 item.ItemId를 확인했습니다. 뒤로 버튼의 ID는

    android.R.id.home

    그런 다음 android.R.id.home 내부에서 finish () 함수 호출을 구현합니다.

    이것은 활동 B를 끝내고 전체 수명주기를 거치지 않고 Acitivy-A를 가져올 것입니다.

내 요구 사항에 대해 이것이 지금까지 최고의 솔루션입니다.

     override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_show_project)

    supportActionBar?.title = projectName
    supportActionBar?.setDisplayHomeAsUpEnabled(true)

}


 override fun onOptionsItemSelected(item: MenuItem?): Boolean {

    when(item?.itemId){

        android.R.id.home -> {
            finish()
        }
    }

    return super.onOptionsItemSelected(item)
}

1

나는 약간의 차이로 동일한 문제가 있었고 Databinding 을 사용 하고 있었고 바인딩 메서드에서 recyclerView 어댑터와 layoutManager를 설정했습니다.

문제는 onResume 후에 데이터 바인딩이 발생 했기 때문에 onResume 후에 내 layoutManager를 재설정하고 매번 원래 위치로 스크롤한다는 의미입니다. 따라서 Databinding 어댑터 메서드에서 layoutManager 설정을 중지하면 다시 정상적으로 작동합니다.


어떻게 성취 했습니까?
Kedar Sukerkar

0

제 경우에는 RecyclerView layoutManager를 XML과 onViewCreated. 할당을 제거하면 onViewCreated수정되었습니다.

with(_binding.list) {
//  layoutManager =  LinearLayoutManager(context)
    adapter = MyAdapter().apply {
        listViewModel.data.observe(viewLifecycleOwner,
            Observer {
                it?.let { setItems(it) }
            })
    }
}

-1

Activity.java :

public RecyclerView.LayoutManager mLayoutManager;

Parcelable state;

    mLayoutManager = new LinearLayoutManager(this);


// Inside `onCreate()` lifecycle method, put the below code :

    if(state != null) {
    mLayoutManager.onRestoreInstanceState(state);

    } 

    @Override
    protected void onResume() {
        super.onResume();

        if (state != null) {
            mLayoutManager.onRestoreInstanceState(state);
        }
    }   

   @Override
    protected void onPause() {
        super.onPause();

        state = mLayoutManager.onSaveInstanceState();

    }   

왜 내가 사용하고 있습니다 OnSaveInstanceState()에서 onPause()다른 활동으로 전환이 onPause가 called.It 그 스크롤 위치를 저장하고 우리가 다른 활동에서 오는 위치를 복원 할 것이지만, 수단.


2
공용 정적 필드가 좋지 않습니다. 글로벌 데이터와 싱글 톤은 좋지 않습니다.
weston

@weston 나는 지금 이해했다. global을 제거하기 위해 savingstate를 onpause로 변경했다.
Steve
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.