룬아님의 취중코딩

Recyclerview의 보여지는 뷰의 index 변화를 알려주는 Listener 본문

개발/안드로이드 개발

Recyclerview의 보여지는 뷰의 index 변화를 알려주는 Listener

룬아님 2019. 8. 13. 22:05

 

리사이클러뷰를 사용하면서 특정 위치의 뷰가 보여지는 시점이라던지 더이상 보이지 않게 되는 시점에 해당 뷰의 위치를 가져와야 하는 경우가 종종있습니다. 저의 경우에는 각 뷰의 노출 횟수를 집계하기 위하여 이 리스너를 직접 구현하여 사용하였습니다.

 

https://github.com/myung6024/VisiblePositionChangeListener

 

myung6024/VisiblePositionChangeListener

리사이클러뷰를 사용하면서 특정 위치의 뷰가 보여지는 시점이라던지 더이상 보이지 않게 되는 시점에 해당 뷰의 위치를 알려주는 Recyclerview listener 입니다. - myung6024/VisiblePositionChangeListener

github.com

 


보여지는 View와 가려지는 View의 position을 감지하는 Linstener

import android.support.annotation.NonNull;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;

public class VisiblePositionChangeListener extends RecyclerView.OnScrollListener {
    public interface OnChangeListener {
        void onFirstVisiblePositionChanged(int position);
        void onLastVisiblePositionChanged(int position);
        void onFirstInvisiblePositionChanged(int position);
        void onLastInvisiblePositionChanged(int position);
    }

    private int firstVisiblePosition;
    private int lastVisiblePosition;
    private final OnChangeListener listener;
    private LinearLayoutManager layoutManager;

    public VisiblePositionChangeListener(LinearLayoutManager linearLayoutManager, OnChangeListener listener) {
        this.listener = listener;
        this.firstVisiblePosition = RecyclerView.NO_POSITION;
        this.lastVisiblePosition = RecyclerView.NO_POSITION;
        this.layoutManager = linearLayoutManager;
    }

    public VisiblePositionChangeListener(LinearLayoutManager linearLayoutManager, OnChangeListener listener) {
        this.listener = listener;
        this.firstVisiblePosition = RecyclerView.NO_POSITION;
        this.lastVisiblePosition = RecyclerView.NO_POSITION;
        this.layoutManager = linearLayoutManager;
    }

    @Override
    public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        int firstPosition = layoutManager.findFirstVisibleItemPosition();
        int lastPosition = layoutManager.findLastVisibleItemPosition();

        if (firstVisiblePosition == RecyclerView.NO_POSITION || lastVisiblePosition == RecyclerView.NO_POSITION) {
            firstVisiblePosition = firstPosition;
            lastVisiblePosition = lastPosition;
            return;
        }

        if (firstPosition < firstVisiblePosition) {
            if (firstVisiblePosition - firstPosition > 1) {
                for (int i = 1; i < firstVisiblePosition - firstPosition + 1; i++) {
                    listener.onFirstVisiblePositionChanged(firstVisiblePosition - i);
                }
            } else {
                listener.onFirstVisiblePositionChanged(firstPosition);
            }
            firstVisiblePosition = firstPosition;
        } else if (firstPosition > firstVisiblePosition) {
            if (firstPosition - firstVisiblePosition > 1) {
                for (int i = firstPosition - firstVisiblePosition; i > 0; i--) {
                    listener.onFirstInvisiblePositionChanged(firstPosition - i);
                }
            } else {
                listener.onFirstInvisiblePositionChanged(firstVisiblePosition);
            }
            firstVisiblePosition = firstPosition;
        }

        if (lastPosition > lastVisiblePosition) {
            if (lastPosition - lastVisiblePosition > 1) {
                for (int i = 1; i < lastPosition - lastVisiblePosition + 1; i++) {
                    listener.onLastVisiblePositionChanged(lastVisiblePosition + i);
                }
            } else {
                listener.onLastVisiblePositionChanged(lastPosition);
            }
            lastVisiblePosition = lastPosition;
        } else if (lastPosition < lastVisiblePosition) {
            if (lastVisiblePosition - lastPosition > 1) {
                for (int i = 0; i < lastVisiblePosition - lastPosition; i++) {
                    listener.onLastInvisiblePositionChanged(lastVisiblePosition - i);
                }
            } else {
                listener.onLastInvisiblePositionChanged(lastVisiblePosition);
            }
            lastVisiblePosition = lastPosition;
        }
    }
}

 

 

 

 


보여지는 View의 position을 감지하는 Linstener

import android.support.annotation.NonNull;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;

public class VisiblePositionChangeListener extends RecyclerView.OnScrollListener {
    public interface OnChangeListener {
        void onFirstVisiblePositionChanged(int position);

        void onLastVisiblePositionChanged(int position);
    }

    private int firstVisiblePosition;
    private int lastVisiblePosition;
    private final OnChangeListener listener;
    private LinearLayoutManager layoutManager;

    public VisiblePositionChangeListener(LinearLayoutManager linearLayoutManager, OnChangeListener listener) {
        this.listener = listener;
        this.firstVisiblePosition = RecyclerView.NO_POSITION;
        this.lastVisiblePosition = RecyclerView.NO_POSITION;
        this.layoutManager = linearLayoutManager;
    }

    public VisiblePositionChangeListener(LinearLayoutManager linearLayoutManager, OnChangeListener listener) {
        this.listener = listener;
        this.firstVisiblePosition = RecyclerView.NO_POSITION;
        this.lastVisiblePosition = RecyclerView.NO_POSITION;
        this.layoutManager = linearLayoutManager;
    }

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

        int firstPosition = layoutManager.findFirstVisibleItemPosition();
        int lastPosition = layoutManager.findLastVisibleItemPosition();

        if (firstVisiblePosition == RecyclerView.NO_POSITION || lastVisiblePosition == RecyclerView.NO_POSITION) {
            firstVisiblePosition = firstPosition;
            lastVisiblePosition = lastPosition;
            return;
        }

        if (firstPosition < firstVisiblePosition) {
            if (firstVisiblePosition - firstPosition > 1) {
                for (int i = 1; i < firstVisiblePosition - firstPosition + 1; i++) {
                    listener.onFirstVisiblePositionChanged(firstVisiblePosition - i);
                }
            } else {
                listener.onFirstVisiblePositionChanged(firstPosition);
            }
            firstVisiblePosition = firstPosition;
        } else if (firstPosition > firstVisiblePosition) {
            firstVisiblePosition = firstPosition;
        }

        if (lastPosition > lastVisiblePosition) {
            if (lastPosition - lastVisiblePosition > 1) {
                for (int i = 1; i < lastPosition - lastVisiblePosition + 1; i++) {
                    listener.onLastVisiblePositionChanged(lastVisiblePosition + i);
                }
            } else {
                listener.onLastVisiblePositionChanged(lastPosition);
            }
            lastVisiblePosition = lastPosition;

        } else if (lastPosition < lastVisiblePosition) {
            lastVisiblePosition = lastPosition;
        }
    }
}

 

 

 


사용법

recyclerView.addOnScrollListener(new VisiblePositionChangeListener(layoutManager,
        new VisiblePositionChangeListener.OnChangeListener() {
            @Override
            public void onFirstVisiblePositionChanged(int position) {
                //첫번째 보이는 아이템이 변경되었을 때
                //보이게 된 아이템의 position을 리턴
            }

            @Override
            public void onLastVisiblePositionChanged(int position) {
                //마지막 보이는 아이템이 변경되었을 때
                //보이게 된 아이템의 position을 리턴
            }
        }
));

 

recyclerView.addOnScrollListener(new VisiblePositionChangeListener(layoutManager,
        new VisiblePositionChangeListener.OnChangeListener() {
            @Override
            public void onFirstVisiblePositionChanged(int position) {
                //첫번째 보이는 아이템이 변경되었을 때
                //보이게 된 아이템의 position을 리턴
            }

            @Override
            public void onLastVisiblePositionChanged(int position) {
                //마지막 보이는 아이템이 변경되었을 때
                //보이게 된 아이템의 position을 리턴
            }

            @Override
            public void onFirstInvisiblePositionChanged(int position) {
                //첫번째 안보이는 아이템이 변경되었을 때
                //안보이게 된 아이템의 position을 리턴
            }

            @Override
            public void onLastInvisiblePositionChanged(int position) {
                //마지막 안보이는 아이템이 변경되었을 때
                //안보이게 된 아이템의 position을 리턴
            }
        }
));

 

리스너에는 보여지는 뷰 위치만 리턴하는 리스너와 가려지는 뷰 위치도 리턴하는 리스너가 따로 구현되어 있습니다. 두 개의 리스너 중 필요한 리스너를 택하여 사용하면 됩니다.

반응형
Comments