리사이클러뷰에서는 기존에 스크롤 이벤트를 관리할 때 setOnScrollListener를 이용해서 OnScrollListener객체를 집어넣어서 해당 로직을 구현하였습니다.
package androidx.recyclerview.widget;
//Set a listener that will be notified of any changes in scroll state or position
//스크롤 상태나 위치의 변경 사항에 대해 알림을 받을 리스너를 설정합니다.
@Deprecated
public void setOnScrollListener(@Nullable OnScrollListener listener) {
mScrollListener = listener;
}
그러나 이방식은 스크롤 동작에 따라 여러 개의 리스너를 추가해야 했고, 유지보수가 어려웠다고 합니다. 그래서 현재는 addOnScrollListener를 이용해서 리스너를 추가하고 removeOnScrollListener를 이용해서 리스너를 삭제한다고 합니다.
package androidx.recyclerview.widget;
private List<OnScrollListener> mScrollListeners;
/**
* Add a listener that will be notified of any changes in scroll state or position.
* 스크롤 상태나 위치의 변경 사항에 대해 알림을 받을 리스너를 추가합니다.
*
* <p>Components that add a listener should take care to remove it when finished.
* Other components that take ownership of a view may call {@link #clearOnScrollListeners()}
* to remove all attached listeners.</p>
*
* 리스너를 추가하는 구성 요소는 완료되면 제거하도록 주의해야 합니다.
* 뷰의 소유권을 갖는 다른 구성 요소는 연결된 모든 리스너를 제거하기
* 위해clearOnScrollListeners()를 호출할 수 있습니다.
*
* @param listener listener to set
*/
public void addOnScrollListener(@NonNull OnScrollListener listener) {
if (mScrollListeners == null) {
mScrollListeners = new ArrayList<>();
}
mScrollListeners.add(listener);
}
/**
* Remove a listener that was notified of any changes in scroll state or position.
* 스크롤 상태나 위치 변경에 대한 알림을 받은 리스너를 제거합니다.
*
* @param listener listener to set or null to clear
*/
public void removeOnScrollListener(@NonNull OnScrollListener listener) {
if (mScrollListeners != null) {
mScrollListeners.remove(listener);
}
}
이처러 리사이클러뷰에 addOnScrollListener를 추가하여 스클롤 이벤트를 추가할 수 있습니다.
package androidx.recyclerview.widget;
/**
* An OnScrollListener can be added to a RecyclerView to receive messages when a scrolling event
* has occurred on that RecyclerView.
* RecyclerView에 스크롤 이벤트가 발생할 때 메시지를 수신하기 위해 OnScrollListener를 RecyclerView에 추가할 수 있습니다.
* <p>
* @see RecyclerView#addOnScrollListener(OnScrollListener)
* @see RecyclerView#clearOnChildAttachStateChangeListeners()
*
*/
public abstract static class OnScrollListener {
/**
* Callback method to be invoked when RecyclerView's scroll state changes.
* RecyclerView의 스크롤 상태가 변경될 때 호출되는 콜백 메서드입니다.
*
* @param recyclerView The RecyclerView whose scroll state has changed.
* @param newState The updated scroll state. One of {@link #SCROLL_STATE_IDLE},
* {@link #SCROLL_STATE_DRAGGING} or {@link #SCROLL_STATE_SETTLING}.
* 업데이트된 스크롤 상태입니다.
* SCROLL_STATE_IDLE, SCROLL_STATE_DRAGGING 또는 SCROLL_STATE_SETTLING 중 하나입니다.
*/
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState){}
/**
* Callback method to be invoked when the RecyclerView has been scrolled. This will be
* called after the scroll has completed.
* RecyclerView가 스크롤될 때 호출되는 콜백 메서드입니다. 스크롤이 완료된 후에 호출됩니다.
*
* <p>
* This callback will also be called if visible item range changes after a layout
* calculation. In that case, dx and dy will be 0.
* 이 콜백은 레이아웃 계산 후 표시되는 항목 범위가 변경되는 경우에도 호출됩니다. 이 경우 dx와 dy는 0이 됩니다.
*
* @param recyclerView The RecyclerView which scrolled.
* @param dx The amount of horizontal scroll. : 가로 스크롤 양
* @param dy The amount of vertical scroll.: 세로 스크롤 양
*/
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy){}
}
위 코드는 addOnScrollListener의 매개변수로 들어가는 OnScrollListener의 클래스 구조입니다.
package androidx.recyclerview.widget;
/**
* The RecyclerView is not currently scrolling.
* RecyclerView는 현재 스크롤되지 않습니다.
* @see #getScrollState()
*/
public static final int SCROLL_STATE_IDLE = 0;
/**
* The RecyclerView is currently being dragged by outside input such as user touch input.
* RecyclerView는 현재 사용자 터치 입력 등 외부 입력에 의해 드래그되고 있습니다.
* @see #getScrollState()
*/
public static final int SCROLL_STATE_DRAGGING = 1;
/**
* The RecyclerView is currently animating to a final position while not under
* outside control.
* RecyclerView는 현재 외부 제어를 받지 않는 동안 최종 위치로 애니메이션을 적용하고 있습니다.
* @see #getScrollState()
*/
public static final int SCROLL_STATE_SETTLING = 2;
onScrollStateChanged의 함수의 newState같은경우 위 3개의 상태중 하나입니다. 대부분 onScrollStateChanged에서 스크롤 이벤트를 관리합니다
package androidx.recyclerview.widget;
/**
* Check if this view can be scrolled vertically in a certain direction.
* 이 뷰를 특정 방향으로 수직으로 스크롤할 수 있는지 확인하세요.
*
* <p>This is without regard to whether the view is enabled or not, or if it will scroll
* in response to user input or not.
* 이는 뷰의 활성화 여부나 사용자 입력에 대한 응답으로 스크롤되는지 여부와 관계가 없습니다.
*
* @param direction Negative to check scrolling up, positive to check scrolling down.
* 위로 스크롤을 확인하려면 음수이고, 아래로 스크롤을 확인하려면 양수입니다.
*
* @return true if this view can be scrolled in the specified direction, false otherwise.
* 이 뷰가 지정된 방향으로 스크롤될 수 있으면 true를 반환하고, 그렇지 않으면 false를 반환합니다.
*/
public boolean canScrollVertically(int direction) {
final int offset = computeVerticalScrollOffset();
final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
if (range == 0) return false;
if (direction < 0) {
return offset > 0;
} else {
return offset < range - 1;
}
}
/**
* Check if this view can be scrolled horizontally in a certain direction.
*
* <p>This is without regard to whether the view is enabled or not, or if it will scroll
* in response to user input or not.
*
* @param direction Negative to check scrolling left, positive to check scrolling right.
* @return true if this view can be scrolled in the specified direction, false otherwise.
*/
public boolean canScrollHorizontally(int direction) {
final int offset = computeHorizontalScrollOffset();
final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
if (range == 0) return false;
if (direction < 0) {
return offset > 0;
} else {
return offset < range - 1;
}
}
canScrollVertically나 canScrollHorizontally 를 이용해서 스크롤 가능한지를 확인할 수도 있습니다. 이것을 이용해서 조건등을 검사할 때 자주 쓰입니다.
'안드로이드 > 안드로이드' 카테고리의 다른 글
[Android/Kotlin] 프래그먼트안 프래그먼트에서 뒤로가기 (0) | 2023.09.04 |
---|---|
[Android/Kotlin] 알림(Notification) - 1, NotificationChannel 속성 (2) | 2023.09.01 |
[Android/Kotlin] 알림(Notification)아이디 채널아이디 (2) | 2023.08.30 |
[Android/Kotlin] 뷰 바인딩(ViewBinding) (2) | 2023.08.28 |
[Android/Kotlin] 리사이클러뷰(RecyclerView) 어댑터 이야기 (0) | 2023.08.08 |