简体   繁体   中英

ListViewDraggingAnimation broken on Android 5 Lollipop

I'm using ListViewDraggingAnimation by DevBytes , but it seems broken on Android Lollipop developer preview 2 (LPX13D). When I drag a row over other rows, those rows will disappear and become no longer clickable (see below). I tried disabling hardware acceleration for the listview but it didn't have any effect.

例

Has anyone experienced the same issue? Any hints? Thanks :)

I found the problem. It came from this flag. StableArrayAdapter.hasStableId .

It fix all problem from this view on Lollipop.

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

To be honest, I don't what causes the problem, but this fix makes no visual errors anymore on any version. And because all that was changed is just visibility of view, I believe it shouldn't create any new functional problems.


Replace this code in function handleCellSwitch() in class DynamicListView :

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

for

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

I tried tinkering with the code and in the end I found a way how to make it display as it was before. But fixing the problem for Lollipop made the same problem appear on KitKat and previous versions instead. So I applied the fix only for android versions higher than KitKat.

My guess is that these two views gets exchanged in the process for some reason on the new Lollipop version. In effect, one of the views gets always displayed while the other one gets always hidden. Would be nice to know where and what was changed in the lollipop android code though...

The proper solution is to turn the visibility of that view back on before it's recycled and then turn it back off before it's drawn.

       ((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);

replace with,

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

The stableid solution is wrong. The IDs are stable and telling it that they aren't is in error. It simply kluges the system into recycling the views the old way. Which was in fact a bad way of doing it and was fixed in lollipop. This is a much more correct solution. Rather than predicting how the .notifyDataSetChanged will affect the views and turning on and off the proper elements given whatever version you're using. This one will turn on the visibility in all cases. Then in the predraw listener to find the view again and turns it back invisible, before it's drawn and after it's in its proper state.

And it doesn't matter, if that view is the same one or not, or some future version with some different way of doing it, or a bad adapter that doesn't actually recycle the views, etc. Stable Ids or non-stable ids (flagged not stable, they still have to be actually stable, but that's easily fixable), it's the way to properly do it and future proofed.

The problem here is that which recycled view you're going to get isn't actually clear (they are half trash recycled views after all), not things you can safely store properties in. The behavior was changed in Lollipop to keep stable views actually stable if they can, you could check in the adapter function and the recycled view will likely already have your data because it will give you the same view back again maximally often. Which is something you want, which is why Lollipop does it that way.

The problem here is that the code says mobileView should be made to be visible (the one you're moving), and the switchView should be made invisible (the one you're switching with). But, these are going to be recycled so they are technically ambiguous which one you'll get back, and depends entirely on how the system is recycling the views, and it's completely allowed to change that behavior for the better, and did.

Ps. I bother to check for null because I personally swap the views at the midway point and it can sometimes end up being null if you hit things just right.

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

...

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

You need to visible the mobileView and switchView before adapter notify. This is work for me.

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

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

    mDownY = mLastEventY;

    final int switchViewStartTop = switchView.getTop();

    updateNeighborViewsForID(mMobileItemId);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM