android - 滑动以显示在 Android 中使用 RecyclerView 创建的列表上的操作按钮
问题描述
我的应用程序的主要活动有一个自定义列表,每个列表项都应该在向左滑动时显示一个与之关联的操作按钮,并在同一个列表项再次向右滑动时隐藏该按钮。现在我试图通过创建 Swipe 检测器类然后将其设置为 ItemHolder 类中列表项的触摸侦听器来检测每个列表项的滑动事件。
但是,由于 RecyclerView 是可滚动的,因此无法检测到对单个列表项的滑动。如何检测对单个列表项的滑动?
MainActivity - onCreate()
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_recycler);
ArrayList<Subject> subjects = new ArrayList<>();
subjects.add(new Subject(1, "Physics"));
subjects.add(new Subject(2, "Chemistry"));
subjects.add(new Subject(3, "Biology"));
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.subject_recycler_list_view);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
SubjectRecyclerListAdapter adapter = new SubjectRecyclerListAdapter(getApplicationContext(), R.layout.row_layout , subjects);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(layoutManager);
}
滑动检测器
public class SwipeDetector implements View.OnTouchListener {
static final int MIN_DISTANCE = 50;
private float downX, downY, upX, upY;
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
downX = event.getX();
downY = event.getY();
// return true;
}
case MotionEvent.ACTION_UP: {
upX = event.getX();
upY = event.getY();
float deltaX = downX - upX;
float deltaY = downY - upY;
// swipe horizontal?
if ( Math.abs(deltaX) > MIN_DISTANCE){
// left or right
if ( deltaX < 0){
Log.i("Swipe Detector","LeftToRightSwipe!");
return true;
}
if ( deltaX > 0){
Log.i("Swipe Detector","RightToLeftSwipe!");
return true;
}
} else{
Log.i("Swipe Detector","Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
}
}
}
return false;
}
}
itemHolder - 构造函数
public SubjectHolder(Context context, View itemView) {
super(itemView);
this.subjectTextView = (TextView) itemView.findViewById(R.id.name);
SwipeDetector swipeDetector = new SwipeDetector();
itemView.setOnTouchListener(swipeDetector);
}
滑动检测适用于除 RecyclerView 的列表项(或任何其他可滚动视图的子项)之外的任何其他视图。如何检测列表项上的滑动?
解决方案
问题已解决,但我不知道这是否是正确的方法,但它确实有效。事情是这样的——
使用两个方法创建一个接口SwipeActions,用于左右滑动的回调。
滑动动作
public interface SwipeActions {
public void onLeftSwipe(MotionEvent e);
public void onRightSwipe(MotionEvent e);
}
然后提到SwipeAction作为 SwipeDetector 的属性之一,然后在构造函数中初始化它。
public class SwipeDetector implements View.OnTouchListener {
static final int MIN_DISTANCE = 50;
private float downX, downY, upX, upY;
public SwipeActions swipeActions;
public SwipeDetector(SwipeActions swipeActions) {
this.swipeActions = swipeActions;
}
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
downX = event.getX();
downY = event.getY();
}
case MotionEvent.ACTION_UP: {
upX = event.getX();
upY = event.getY();
float deltaX = downX - upX;
float deltaY = downY - upY;
if ( Math.abs(deltaX) > MIN_DISTANCE){
if ( deltaX < 0){
swipeActions.onRightSwipe(event);
return true;
}
if ( deltaX > 0){
swipeActions.onLeftSwipe(event);
return true;
}
} else{
Log.i("Swipe Detector","Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
}
}
}
return false;
}
}
Swipe Actions将MotionEvent对象作为参数,该参数将在MainActivity中用于检索执行滑动的子视图的对象。所以将MainActivity修改为这个 -
MainActivity - onCreate
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_recycler);
ArrayList<Subject> subjects = new ArrayList<>();
subjects.add(new Subject(1, "Physics"));
subjects.add(new Subject(2, "Chemistry"));
subjects.add(new Subject(3, "Biology"));
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.subject_recycler_list_view);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
SubjectRecyclerListAdapter adapter = new SubjectRecyclerListAdapter(getApplicationContext(), R.layout.row_layout , subjects);
SwipeDetector swipeDetector = new SwipeDetector(new SwipeActions() {
@Override
public void onLeftSwipe(MotionEvent evnt) {
View childView = recyclerView.findChildViewUnder(evnt.getX(), evnt.getY());
if(childView != null) {
// Perform your action on childView (Swiped List Item)
}
else {
Log.i("Main Recycler Activity", "Child View is Null");
}
}
@Override
public void onRightSwipe(MotionEvent evnt) {
View childView = recyclerView.findChildViewUnder(evnt.getX(), evnt.getY());
if(childView != null) {
if(swipedViews.contains(childView)) {
// Perform your action on childView (Swiped List Item)
}
}
else {
Log.i("Main Recycler Activity", "Child View is Null");
}
}
});
recyclerView.setOnTouchListener(swipeDetector);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(layoutManager);
}
另外,我从itemHolder中删除了TouchListener
itemHolder - 构造函数
public SubjectHolder(Context context, View itemView) {
super(itemView);
this.subjectTextView = (TextView) itemView.findViewById(R.id.name);
}
推荐阅读
- cpu - 测试 XDP 与 DPDK
- flow-project - tutorial03_rlib 中的错误
- javascript - 当函数内部不使用事件参数时,为什么这个handleBlur函数带有事件参数?
- asp.net - 调试器是否有可能同时运行两次?
- python - 在这段代码中,我得到 UnboundLocalError: local variable 'click' referenced before assignment。我不知道为什么?
- javascript - next.js、javascript、graphql、react js 中的 Apollo 客户端问题
- javascript - 如何将两个函数添加到一个事件监听器
- pycharm - .rc 文件的 PyCharm 文件类型关联(语法高亮)
- c++ - 如何在合并排序中计算比较和交换(反转)?[C++]
- swift - 当应用程序在后台时扫描外围设备(例如屏幕锁定时)