SwipeListView само един отворен елемент наведнъж

Този въпрос се отнася до компонента 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 в дейността, която раздува списъка.


person Adrian Olar    schedule 24.03.2014    source източник
comment
Удивително, благодаря! Разрешава и други проблеми, като този: github.com/47deg/android-swipelistview/ проблеми/131   -  person ggurov    schedule 31.05.2014
comment
Работи добре без никакви проблеми.   -  person Madhur Ahuja    schedule 27.06.2014
comment
tnx реши проблема ми...   -  person Dhaval Parmar    schedule 06.08.2014
comment
какви видове промени трябва да направя на OnTouch? къде трябва да добавя кодовете?   -  person Armin    schedule 07.10.2014
comment
Здравей Адриан, наистина бих искал този код да бъде част от проекта 47deg. Ако нямате време, ще имам нещо против да изпратя PR с това (ще ви призная, както искате)   -  person Kibi    schedule 07.12.2014
comment
Ако си спомням правилно, всъщност мисля, че го направих, но не съм сигурен в това. Ако искате можете да го проверите.   -  person Adrian Olar    schedule 07.12.2014


Отговори (4)


Минуси: не затваря реда, отворен от 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);
person lordmegamax    schedule 13.01.2015

Вашата корекция работи, но има начин да го направите, без да засягате оригиналния код:

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;
    }
}

Трябва обаче да изпратите заявка за изтегляне, за да приложите кода си, тъй като това ще поправи грешката.

Източник: https://github.com/47deg/android-swipelistview/issues/46

person spacebiker    schedule 03.09.2014
comment
Благодаря за вашите предложения, тъй като това не е скорошна публикация, не си спомням сега, но е много възможно и аз да съм пробвал вашата корекция, първоначално да е работил, но след това да се провали по пътя, досега това, което публикувах, не изглеждаше за показване на грешки. - person Adrian Olar; 03.09.2014
comment
@spacebiker: Здравейте, възможно ли е да затворите определен елемент, който вече е отворен в списъка. Използвах closeAnimate(postion), но не работи. - person Aerrow; 14.11.2014

Ако ще модифицирате самата библиотека swipelistview, имам по-просто решение.

Добавете следния блок if към SwipeListViewTouchListener.java в метода onTouch точно в началото на case MotionEvent.ACTION_DOWN:

if(lastOpenedPosition != downPosition && opened.get(lastOpenedPosition)) {
    closeAnimate(lastOpenedPosition);
    return false;
}

Създайте поле int lastOpenedPosition и го инициализирайте на 0, а в метода generateRevealAnimate вътре в блока if (aux) добавете:

lastOpenedPosition = position;

Също така бих добавил конфигурационна променлива (в res/values/swipelistview_attrs.xml) към SwipeListView и бих я добавил към блока onTouch if, за да добавя възможност за изключване и включване на тази функция. Това основно води до това, че ако списъкът бъде докоснат, докато ред е отворен, редът ще се затвори. Което, imho, е по-добра функционалност от затварянето на ред само след като приключите с отварянето на друг ред.

person Leo K    schedule 22.10.2014
comment
Здравейте, благодаря ви за отговора, всъщност се натъкнах на вашето решение преди, работи, но не през цялото време. Имах нужда от нещо, което да работи с по-висока точност. Това, което дадох тук, е най-доброто за мен. - person Adrian Olar; 23.10.2014
comment
Интересно, спомняте ли си в какви ситуации това не работи? - person Leo K; 23.10.2014
comment
Не е нещо скорошно, както виждате публикацията е много стара. Проблемите, които срещнах, бяха случайни сривове и грешки с анимацията за списъка. - person Adrian Olar; 23.10.2014

Да, SwipeListView на оригиналните кодове може да отвори много елементи едновременно. Вашият кодов сегмент тук може ли да отваря един елемент наведнъж? Или когато отворите друг елемент, отворените елементи ще бъдат затворени?

person Community    schedule 21.04.2014
comment
След като един елемент е отворен и се опитате да отворите друг, предишният елемент ще се затвори, когато отворите другия. - person Adrian Olar; 21.04.2014