programing

선택한 항목을 맨 위에 표시하려면 RecyclerView 스크롤

skycolor 2023. 8. 5. 10:01
반응형

선택한 항목을 맨 위에 표시하려면 RecyclerView 스크롤

스크롤하는 방법을 찾고 있습니다.RecyclerView선택한 항목을 맨 위에 표시합니다.

ListView저는 그것을 할 수 있었습니다.scrollTo(x,y)그리고 중심에 있어야 하는 요소의 맨 위를 얻는 것.

다음과 같은 것:

@Override
public void onItemClick(View v, int pos){
    mylistView.scrollTo(0, v.getTop());
}

문제는 그것이RecyclerView시 됩니다.scrollTo라고 말하는

RecyclerView는 절대 위치로 스크롤하는 것을 지원하지 않습니다.

스롤하방법을 어떻게 ?RecyclerView선택한 항목을 보기의 맨 위에 놓으시겠습니까?

을 사용하는 LinearLayoutManager Staged 는또시지정차 지정▁or▁staggered.GridLayoutManager각각 위치 이동 스크롤이 있습니다.항목 시작의 위치와 간격띄우기를 모두 사용하는 Offset 메서드 사용RecyclerView필요한 작업을 수행할 수 있습니다(오프셋을 0으로 설정하면 상단에 정렬됩니다).

예를 들어:

//Scroll item 2 to 20 pixels from the top
linearLayoutManager.scrollToPositionWithOffset(2, 20);

수직 선형 레이아웃 관리자를 찾는 경우 사용자 정의를 사용하여 부드러운 스크롤을 수행할 수 있습니다.LinearSmoothScroller:

import android.content.Context;
import android.graphics.PointF;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.LinearSmoothScroller;
import android.support.v7.widget.RecyclerView;

public class SnappingLinearLayoutManager extends LinearLayoutManager {

    public SnappingLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
    }

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
                                       int position) {
        RecyclerView.SmoothScroller smoothScroller = new TopSnappedSmoothScroller(recyclerView.getContext());
        smoothScroller.setTargetPosition(position);
        startSmoothScroll(smoothScroller);
    }

    private class TopSnappedSmoothScroller extends LinearSmoothScroller {
        public TopSnappedSmoothScroller(Context context) {
            super(context);

        }

        @Override
        public PointF computeScrollVectorForPosition(int targetPosition) {
            return SnappingLinearLayoutManager.this
                    .computeScrollVectorForPosition(targetPosition);
        }

        @Override
        protected int getVerticalSnapPreference() {
            return SNAP_TO_START;
        }
    }
}

한 후 합니다.recyclerView.smoothScrollToPosition(pos);의 맨 로 이동합니다.

//항목 pos 스크롤

linearLayoutManager.scrollToPositionWithOffset(pos, 0);

당신은 그냥 전화하면 됩니다.recyclerview.scrollToPosition(position)괜찮아요!

또는 구현합니다.getRecyclerview()그들 안에.

도움이 되길 바랍니다.

스크롤 모션을 표시하지 않고 자동으로 스크롤하려면 다음 코드를 작성해야 합니다.

mRecyclerView.getLayoutManager().scrollToPosition(position);

스크롤 모션을 표시하려면 다음 코드를 추가해야 합니다.=>1단계: SmoothScroller를 선언해야 합니다.

RecyclerView.SmoothScroller smoothScroller = new
                LinearSmoothScroller(this.getApplicationContext()) {
                    @Override
                    protected int getVerticalSnapPreference() {
                        return LinearSmoothScroller.SNAP_TO_START;
                    }
                };

=>2단계: 특정 위치로 스크롤을 수행하고자 하는 이벤트는 이 코드를 추가해야 합니다.=>먼저 목표 위치를 SmoothScroller로 설정해야 합니다.

smoothScroller.setTargetPosition(position);

=>그러면 SmoothScroller를 LayoutManager로 설정해야 합니다.

mRecyclerView.getLayoutManager().startSmoothScroll(smoothScroller);

이 방법을 간단히 다음과 같이 부릅니다.

((LinearLayoutManager)recyclerView.getLayoutManager()).scrollToPositionWithOffset(yourItemPosition,0);

다음 대신:

recyclerView.scrollToPosition(yourItemPosition);

속도 조절기와 동일

public class SmoothScrollLinearLayoutManager extends LinearLayoutManager {
private static final float MILLISECONDS_PER_INCH = 110f;
private Context mContext;

public SmoothScrollLinearLayoutManager(Context context,int orientation, boolean reverseLayout) {
    super(context,orientation,reverseLayout);
    mContext = context;
}

@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
                                   int position) {
    RecyclerView.SmoothScroller smoothScroller = new TopSnappedSmoothScroller(recyclerView.getContext()){
        //This controls the direction in which smoothScroll looks for your view
        @Override
        public PointF computeScrollVectorForPosition(int targetPosition) {
            return new PointF(0, 1);
        }

        //This returns the milliseconds it takes to scroll one pixel.
        @Override
        protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
            return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
        }
    };
    smoothScroller.setTargetPosition(position);
    startSmoothScroll(smoothScroller);
}


private class TopSnappedSmoothScroller extends LinearSmoothScroller {
    public TopSnappedSmoothScroller(Context context) {
        super(context);

    }

    @Override
    public PointF computeScrollVectorForPosition(int targetPosition) {
        return SmoothScrollLinearLayoutManager.this
                .computeScrollVectorForPosition(targetPosition);
    }

    @Override
    protected int getVerticalSnapPreference() {
        return SNAP_TO_START;
    }
}
}

제게 효과가 있었던 것을 멋지게 시도해 보세요!

private static int displayedposition = 0;

이제 활동에서 재활용자 보기의 위치를 확인합니다.

myRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                LinearLayoutManager llm = (LinearLayoutManager) myRecyclerView.getLayoutManager();


                displayedposition = llm.findFirstVisibleItemPosition();


            }
        });

보기에 표시된 이전 사이트를 배치할 위치에 이 문을 배치합니다.

LinearLayoutManager llm = (LinearLayoutManager) mRecyclerView.getLayoutManager();
        llm.scrollToPositionWithOffset(displayedposition , youList.size());

그게 다예요, 저한테는 잘 먹혔어요 \o/

RecyclerView를 새로 고친 후 스크롤 위치를 복원하기 위해 수행한 작업 단추 클릭:

if (linearLayoutManager != null) {

    index = linearLayoutManager.findFirstVisibleItemPosition();
    View v = linearLayoutManager.getChildAt(0);
    top = (v == null) ? 0 : (v.getTop() - linearLayoutManager.getPaddingTop());
    Log.d("TAG", "visible position " + " " + index);
}

else{
    index = 0;
}

linearLayoutManager = new LinearLayoutManager(getApplicationContext());
linearLayoutManager.scrollToPositionWithOffset(index, top);

linearLayoutManager 객체를 생성하기 전 및 인스턴스화한 후에 맨 위에서 볼 수 있는 첫 번째 항목의 오프셋 가져오기선형 레이아웃 관리자 개체의 오프셋을 사용하여 호출되었습니다.

제가 왜 최고의 답을 찾지 못했는지는 모르겠지만 정말 간단합니다.

recyclerView.smoothScrollToPosition(position);

오류 없음

애니메이션 만들기

여기서 추가할 수 있는 것은 어떻게 그것이 함께 작동하도록 만드는지입니다.DiffUtil그리고.ListAdapter

당신은 그 전화를 주목할 수 있습니다.recyclerView.scrollToPosition(pos)또는(recyclerView.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(pos, offset)바로 다음에 전화하면 작동하지 않을 것입니다.adapter.submitList이는 different가 백그라운드 스레드에서 변경 사항을 찾은 다음 어댑터에 변경 사항을 비동기적으로 알리기 때문입니다.SO에서 저는 이 문제를 해결하기 위해 불필요한 지연 등의 오답을 여러 번 보았습니다.

상황을 적절하게 처리하기 위해submitList에는 변경 사항이 적용될 때 호출되는 콜백이 있습니다.

따라서 이 경우 적절한 코틀린 구현은 다음과 같습니다.

//memorise target item here and a scroll offset if needed
adapter.submitList(items) { 
    val pos = /* here you may find a new position of the item or just use just a static position. It depends on your case */
    recyclerView.scrollToPosition(pos) 
}
//or
adapter.submitList(items) { recyclerView.smoothScrollToPosition(pos) }
//or etc
adapter.submitList(items) { (recyclerView.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(pos, offset) }

소개

맨 위에 마지막 항목을 표시하는 방법을 설명하는 답변이 없습니다.따라서 나머지 항목을 채우기에 충분할 정도로 위 또는 아래에 있는 항목에 대해서만 답이 작동합니다.RecyclerView예를 들어 59개의 요소가 있고 56번째 요소가 선택된 경우 아래 그림과 같이 맨 위에 있어야 합니다.

example

다음 단락에서는 이를 구현하는 방법을 살펴보겠습니다.

해결책

우리는 그 사건들을 처리할 수 있습니다.linearLayoutManager.scrollToPositionWithOffset(pos, 0)는 추논가 에 있습니다.AdapterRecyclerView항목 으로써 (입니다.)RecyclerView뷰일 수 .) 사용자 정의 여백은 루트 뷰 높이와 항목 높이 사이의 차이일 수 있습니다.그래서, 당신의 Adapter위해서RecyclerView다음과 같이 표시됩니다.

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

    int bottomHeight = 0;
    int itemHeight = holder.itemView.getMeasuredHeight();
    // if it's the last item then add a bottom margin that is enough to bring it to the top
    if (position == mDataSet.length - 1) {
        bottomHeight = Math.max(0, mRootView.getMeasuredHeight() - itemHeight);
    }
    RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)holder.itemView.getLayoutParams();
    params.setMargins(0, 0, params.rightMargin, bottomHeight);
    holder.itemView.setLayoutParams(params);

    ...
} 
...

만약 당신이LayoutManager이라LinearLayoutManager사용할 수 있습니다.scrollToPositionWithOffset(position,0);목록에서 항목을 첫 번째로 볼 수 있는 항목으로 만듭니다.그렇지 않으면 다음을 사용할 수 있습니다.smoothScrollToPosition에서.RecyclerView직접적으로.

저는 결국 아래 코드를 사용하게 되었습니다.

 RecyclerView.LayoutManager layoutManager = mainList.getLayoutManager();
        if (layoutManager instanceof LinearLayoutManager) {
            // Scroll to item and make it the first visible item of the list.
            ((LinearLayoutManager) layoutManager).scrollToPositionWithOffset(position, 0);
        } else {
            mainList.smoothScrollToPosition(position);
        }

.
에게 많은 이 되었습니다. 수 있습니다. 청취자를 클릭하면 어댑터의 위치를 얻을 수 있습니다.

layoutmanager.scrollToPosition(int position);

나의 경우 나의RecyclerView 패딩 .

<android.support.v7.widget.RecyclerView
     ...
     android:paddingTop="100dp"
     android:clipToPadding="false"
/>

그런 다음 항목을 맨 위로 스크롤하려면 다음을 수행해야 합니다.

recyclerViewLinearLayoutManager.scrollToPositionWithOffset(position, -yourRecyclerView.getPaddingTop());

만에약라면 .scrollToPositionRecyclerView가 NestedScrollView 내부에 있었다는 것을 회사에서 알리지 않습니다. 이 게시물을 참조하십시오.

이것은 꽤 간단합니다.

recyclerView.scrollToPosition(position)

중첩된 스크롤 뷰 내에 Recycler 뷰가 있는 경우:

val y = recyclerview.getChildAt(0).y
recyclerview.smoothScrollTo(0, y.toInt())

Recycler 뷰가 중첩된 스크롤 뷰 내부에 없는 경우:

recyclerview.smoothScrollToPosition(index) 

또는

recyclerview.layoutManager?.smoothScrollToPosition(recyclerview, null ,index)

아래 코드를 사용하여 항목(이 보기)을 맨 위로 부드럽게 스크롤합니다.
높이가 다른 그리드 레이아웃 관리자에서도 작동합니다.

View firstView = mRecyclerView.getChildAt(0);
int toY = firstView.getTop();
int firstPosition = mRecyclerView.getChildAdapterPosition(firstView);
View thisView = mRecyclerView.getChildAt(thisPosition - firstPosition);
int fromY = thisView.getTop();

mRecyclerView.smoothScrollBy(0, fromY - toY);

빠른 해결책으로 충분히 효과가 있는 것 같습니다.

언급URL : https://stackoverflow.com/questions/26875061/scroll-recyclerview-to-show-selected-item-on-top

반응형