一个同步监听RecyclerView smoothScrollToPosition解决方案
2024-11-30 13:29:24
michael007js
11
import android.util.Log;
import android.view.View;
import android.view.animation.Interpolator;
import android.widget.LinearLayoutManager;
import android.widget.Scroller;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.concurrent.atomic.AtomicBoolean;
public class CustomRecyclerView extends RecyclerView {
public CustomRecyclerView(@NonNull android.content.Context context) {
super(context);
}
public CustomRecyclerView(@NonNull android.content.Context context, @androidx.annotation.Nullable android.util.AttributeSet attrs) {
super(context, attrs);
}
public CustomRecyclerView(@NonNull android.content.Context context, @androidx.annotation.Nullable android.util.AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void smoothScrollToPosition(int position, final OnSmoothScrollToPositionAnimationCallBack callback) {
final AtomicBoolean isScrollStarted = new AtomicBoolean(false);
final AtomicBoolean isScrollFinished = new AtomicBoolean(false);
final int targetPosition = position;
// 创建一个临时的滚动监听器用于监听此次滚动过程
final OnScrollListener tempScrollListener = new OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
// 滚动停止,意味着此次smoothScrollToPosition操作基本结束
int currentPosition = ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
if (currentPosition == targetPosition) {
isScrollFinished.set(true);
if (callback!= null) {
callback.onScrollToPositionFinished(currentPosition);
}
}
}
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (!isScrollStarted.get()) {
// 首次滚动时,标记滚动开始,并回调告知外部开始滚动了
isScrollStarted.set(true);
if (callback!= null) {
callback.onScrollToPositionStarted(targetPosition);
}
}
int currentPosition = ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
if (callback!= null) {
callback.onScrolling(currentPosition);
}
}
};
// 添加临时滚动监听器
addOnScrollListener(tempScrollListener);
// 使用Scroller来模拟smoothScrollToPosition的滚动过程(这里简单示例,实际更复杂些)
Scroller scroller = new Scroller(getContext(), new Interpolator() {
@Override
public float getInterpolation(float input) {
return input;
}
});
scroller.startScroll(0, 0, 0, 1000, 1000);
// 移除临时滚动监听器,避免后续无关滚动也触发这个监听器逻辑
postDelayed(new Runnable() {
@Override
public void run() {
removeOnScrollListener(tempScrollListener);
}
}, 1000);
}
public interface OnSmoothScrollToPositionAnimationCallBack {
void onScrollToPositionStarted(int targetPosition);
void onScrolling(int currentPosition);
void onScrollToPositionFinished(int finalPosition);
}
}
使用方式
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import android.os.Bundle;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CustomRecyclerView recyclerView = findViewById(R.id.customRecyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
List<String> dataList = new ArrayList<>();
for (int i = 0; i < 50; i++) {
dataList.add("Item " + i);
}
recyclerView.smoothScrollToPosition(20, new CustomRecyclerView.OnSmoothScrollToPositionAnimationCallBack() {
@Override
public void onScrollToPositionStarted(int targetPosition) {
Log.d("RecyclerViewScroll", "滚动开始,目标位置: " + targetPosition);
}
@Override
public void onScrolling(int currentPosition) {
Log.d("RecyclerViewScroll", "正在滚动,当前位置: " + currentPosition);
}
@Override
public void onScrollToPositionFinished(int finalPosition) {
Log.d("RecyclerViewScroll", "滚动结束,最终位置: " + finalPosition);
}
});
}
}