Подтвердить что ты не робот

ListViewDraggingAnimation сломан на Android 5 Lollipop

Я использую ListViewDraggingAnimation DevBytes, но он кажется сломанным на Android Lollipop preview preview 2 (LPX13D). Когда я перетаскиваю строку поверх других строк, эти строки исчезают и становятся недоступными для кликов (см. Ниже). Я попытался отключить аппаратное ускорение для списка, но это не имело никакого эффекта.

Example

Кто-нибудь испытал ту же проблему? Любые намеки? Спасибо:)

4b9b3361

Ответ 1

Я нашел проблему. Это произошло из этого флага. StableArrayAdapter.hasStableId.

Исправлена ​​вся проблема из этого представления на Lollipop.

@Override
public boolean hasStableIds()
{
    return android.os.Build.VERSION.SDK_INT < 20;
}

Ответ 2

Честно говоря, я не причиняю проблемы, но это исправление больше не приводит к визуальным ошибкам в любой версии. И поскольку все, что было изменено, - это просто видимость взгляда, я считаю, что он не должен создавать никаких новых функциональных проблем.


Замените этот код в функции handleCellSwitch() в классе DynamicListView:

mobileView.setVisibility(View.VISIBLE);
switchView.setVisibility(View.INVISIBLE);

для

if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.KITKAT){
    mobileView.setVisibility(View.VISIBLE);
    switchView.setVisibility(View.INVISIBLE);
} else{
    mobileView.setVisibility(View.INVISIBLE);
    switchView.setVisibility(View.VISIBLE);
}

Я попытался поработать с кодом, и в конце концов я нашел способ сделать его отображаемым, как было раньше. Но исправление проблемы для Lollipop создало ту же проблему, что и в KitKat и предыдущих версиях. Поэтому я применил исправление только для версий Android выше, чем KitKat.

Моя догадка заключается в том, что эти два представления обмениваются в процессе по какой-то причине новой версией Lollipop. Фактически, один из просмотров всегда отображается, а другой всегда скрыт. Было бы неплохо узнать, где и что было изменено в коде для Android с леденец, хотя...

Ответ 3

Правильное решение состоит в том, чтобы снова включить видимость этого вида, прежде чем его перерабатывать, а затем отбросить назад, прежде чем нарисовать.

       ((BaseAdapter) getAdapter()).notifyDataSetChanged();

        mDownY = mLastEventY;

        final int switchViewStartTop = switchView.getTop();

        mobileView.setVisibility(View.VISIBLE);
        switchView.setVisibility(View.INVISIBLE);

        updateNeighborViewsForID(mMobileItemId);

        final ViewTreeObserver observer = getViewTreeObserver();
        observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            public boolean onPreDraw() {
                observer.removeOnPreDrawListener(this);

заменить,

        mobileView.setVisibility(VISIBLE);
        ((BaseAdapter) getAdapter()).notifyDataSetChanged();


        mDownY = mLastEventY;

        final int switchViewStartTop = switchView.getTop();

        updateNeighborViewsForID(mMobileItemId);

        final ViewTreeObserver observer = getViewTreeObserver();
        observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            public boolean onPreDraw() {
                observer.removeOnPreDrawListener(this);

                View mobileView = getViewForID(mMobileItemId);
                if (mobileView != null) mobileView.setVisibility(INVISIBLE);

Устойчивое решение ошибочно. Идентификаторы являются стабильными и говорят, что они не являются ошибками. Это просто заставляет систему перерабатывать взгляды по-старому. На самом деле это был плохой способ сделать это и зафиксирован на леденец. Это гораздо более правильное решение. Вместо того, чтобы предсказывать, как .notifyDataSetChanged повлияет на представления и включит и выключит соответствующие элементы, учитывая любую версию, которую вы используете. В этом случае во всех случаях будет отображаться видимость. Затем в предварительном прослушивателе, чтобы снова найти представление и вернуть его обратно, невидимым, прежде чем он нарисован и после него в правильном состоянии.

И это не имеет значения, если это мнение одно и то же или нет, или какая-то будущая версия с каким-то другим способом сделать это, или плохой адаптер, который фактически не перерабатывает представления и т.д. Стабильные идентификаторы или нестабильные идентификаторы (отмеченные нестабильно, они все равно должны быть на самом деле стабильными, но это легко фиксируется), это способ правильно сделать это и будущим.

Проблема заключается в том, что переработанное представление, которое вы собираетесь получить, на самом деле не ясно (в конце концов, это половина переработанных видов мусора), а не вещи, в которые вы можете безопасно хранить свойства. Поведение было изменено в Lollipop, чтобы сохранить стабильные представления на самом деле стабильны, если они могут, вы можете проверить функцию адаптера, и переработанное представление, скорее всего, уже имеет ваши данные, потому что оно даст вам тот же обзор назад максимально часто. Это то, что вы хотите, поэтому Lollipop делает это именно так.

Проблема заключается в том, что в коде говорится, что mobileView должен быть видимым (тот, который вы перемещаете), и switchView должен быть невидимым (тот, с которым вы переключаетесь). Но они будут переработаны, поэтому они технически неоднозначны, и вы полностью вернетесь к тому, как система перерабатывает взгляды, и она полностью позволила изменить это поведение к лучшему и сделала.

Ps. Я позаботился о том, чтобы проверить значение null, потому что я лично меняю взгляды на середине, и иногда это может быть нулевым, если вы просто нажмете на вещи.

    int deltaYTotal = (mHoverCellOriginalBounds.bottom + mHoverCellOriginalBounds.top) / 2
            + mTotalOffset + deltaY;

...

        boolean isBelow = (belowView != null) && (deltaYTotal > belowView.getTop());
        boolean isAbove = (aboveView != null) && (deltaYTotal < aboveView.getBottom());

Ответ 4

Вам нужно увидеть мобильное приложение и switchView перед уведомлением адаптера. Это работа для меня.

 mobileView.setVisibility(View.VISIBLE);
 switchView.setVisibility(View.INVISIBLE);

 ((BaseAdapter) getAdapter()).notifyDataSetChanged();

    mDownY = mLastEventY;

    final int switchViewStartTop = switchView.getTop();

    updateNeighborViewsForID(mMobileItemId);