SwipeListView一次只能打开一个项目

13

这个问题涉及SwipeListView组件,该组件可以在https://github.com/47deg/android-swipelistview找到。

在尝试了几种在网上找到的实现和修复方法之后,我决定对源代码进行一些修改。

我会在这里发布它,因为我知道这是一个已知的问题,并且我找到的所有版本最终都证明有一些问题。

SwipeListViewTouchListener.java已经发生了以下更改:

...
/**
     * Create reveal animation
     *
     * @param view      affected view
     * @param swap      If will change state. If "false" returns to the original
     *                  position
     * @param swapRight If swap is true, this parameter tells if movement is toward
     *                  right or left
     * @param position  list position
     */
    private void generateRevealAnimate(final View view, final boolean swap, final boolean swapRight, final int position) {
        int moveTo = 0;
        if (opened.get(position)) {
            if (!swap) {
                moveTo = openedRight.get(position) ? (int) (viewWidth - rightOffset) : (int) (-viewWidth + leftOffset);
            }
        } else {
            if (swap) {
                moveTo = swapRight ? (int) (viewWidth - rightOffset) : (int) (-viewWidth + leftOffset);
            }
        }
        final boolean aux = !opened.get(position);
        if(swap) {
            opened.set(position, aux);
            openedRight.set(position, swapRight);
        }

        animate(view).translationX(moveTo).setDuration(animationTime).setListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                swipeListView.resetScrolling();

                if (swap) {
                    if (aux) {
                        swipeListView.onOpened(position, swapRight);
                    } else {
                        swipeListView.onClosed(position, openedRight.get(position));
                    }
                }
                // if (aux || !swap) {
                // resetCell();
                // }
            }
        });
    }
...

/**
     * Close all opened items
     */

    void closeOtherOpenedItems() {
        if (opened != null && downPosition != SwipeListView.INVALID_POSITION) {
            int start = swipeListView.getFirstVisiblePosition();
            int end = swipeListView.getLastVisiblePosition();
            for (int i = start; i <= end; i++) {
                if (opened.get(i) && i != downPosition) {
                    closeAnimate(swipeListView.getChildAt(i - start).findViewById(swipeFrontView), i);
                }
            }
        }

    }
...

/**
     * @see View.OnTouchListener#onTouch(android.view.View,
     * android.view.MotionEvent)
     */
    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
...
closeOtherOpenedItems();
view.onTouchEvent(motionEvent);
return true;
}

未提及的其余代码相同。

非常感谢任何评论,这些更改可以使您无需在填充列表的活动中实现SwipeListViewOnTouchListener


太棒了,谢谢!它还解决了其他问题,比如这个:https://github.com/47deg/android-swipelistview/issues/131 - ggurov
没有任何问题,运行得非常好。 - Madhur Ahuja
谢谢,解决了我的问题... - Dhaval Parmar
我应该在"OnTouch"上做哪些更改?我应该在哪里添加代码? - Armin
嗨,Adrian,我真的希望这段代码能成为47deg项目的一部分。如果你没有时间,那么我提交一个PR是否可以(我会按照你想要的方式给你信用)? - Kibi
如果我没记错的话,我想我确实做过那件事,但我不确定。如果你想的话,可以检查一下。 - Adrian Olar
5个回答

3
缺点:未能关闭由openAnimate()打开的行。
   BaseSwipeListViewListener swipeListViewListener = new BaseSwipeListViewListener() {
    int openItem = -1;

    @Override
    public void onStartOpen(int position, int action, boolean right) {
        super.onStartOpen(position, action, right);

        if (openItem > -1)
            swipeListView.closeAnimate(openItem);

        openItem = position;
    }
   }

或者更好的方法:
 @Override
    public void onStartOpen(int position, int action, boolean right) {
        super.onStartOpen(position, action, right);
        swipeListView.closeOpenedItems();
    }

将监听器设置到listView上:

   swipeListView.setSwipeListViewListener(swipeListViewListener);

2
你的修复方案可行,但也有一种方法可以在不影响原始代码的情况下实现:
swipeListView.setSwipeListViewListener(new BaseSwipeListViewListener() {
    int openItem = -1;
    int lastOpenedItem = -1;
    int lastClosedItem = -1;

    @Override
    public void onOpened(int position, boolean toRight) {
        lastOpenedItem = position;
        if (openItem > -1 && lastOpenedItem != lastClosedItem) {
            swipeListView.closeAnimate(openItem);
        }
        openItem = position;
    }

    @Override
    public void onStartClose(int position, boolean right) {
        Log.d("swipe", String.format("onStartClose %d", position));
        lastClosedItem = position;
    }
}

你应该通过发送一个Pull Request来应用你的代码,这可以修复这个bug。
来源:https://github.com/47deg/android-swipelistview/issues/46

感谢您的建议,由于这不是最近的帖子,我现在不记得了,但很有可能我也尝试过您的修复方法,一开始有效,但后来失败了,到目前为止,我发布的内容似乎没有显示错误。 - Adrian Olar
@spacebiker:你好,是否有可能关闭列表中已经打开的特定项目。我使用了closeAnimate(position),但它没有起作用。 - Aerrow

1
swipeListView.setSwipeListViewListener(new BaseSwipeListViewListener() {
//...
  @Override
  public void onClickBackView(int position) {
    //DELETE ITEM
    adapter.notifyDataSetChanged();
    swipeListView.closeOpenedItems();
  }
//...
});

1
如果您要修改swipelistview库本身,我有一个更简单的解决方案。
请在SwipeListViewTouchListener.java中的onTouch方法中,在case MotionEvent.ACTION_DOWN:之前添加以下if块:
if(lastOpenedPosition != downPosition && opened.get(lastOpenedPosition)) {
    closeAnimate(lastOpenedPosition);
    return false;
}

创建一个名为lastOpenedPosition的整型字段,并将其初始化为0,在generateRevealAnimate方法中,if(aux)块内添加以下内容:
lastOpenedPosition = position;

我还会添加一个配置变量(在res/values/swipelistview_attrs.xml中)到SwipeListView,并将其添加到onTouch if块中,以增加打开或关闭此功能的能力。这基本上意味着,如果在打开一行之后触摸了列表,则该行将关闭。在我看来,这比仅在完成打开另一行后才关闭该行具有更好的功能。

嗨,感谢您的回复,我之前确实看到过您的解决方案,它可以工作,但并不总是有效。我需要一些更高准确度的东西。我在这里提供的是对我最有效的一个。 - Adrian Olar
有趣的是,你记得在什么样的情况下这种方法行不通吗? - Leo K
这并不是最近的事情,正如你所看到的帖子非常古老。我遇到的问题是列表动画的随机崩溃和错误。 - Adrian Olar

-1

是的,原始代码中的SwipeListView可以同时打开多个项目。你在这里的代码段只能一次打开一个项目吗?或者当打开另一个项目时,已经打开的项目会被关闭吗?


当您打开一个项目并尝试打开另一个项目时,先前的项目将关闭以便您打开另一个项目。 - Adrian Olar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接