在Android 5 Lollipop上打破的ListViewDraggingAnimation

Ven*_*r85 29 android android-listview android-5.0-lollipop

我使用ListViewDraggingAnimation通过的DevBytes,但似乎在Android棒棒糖开发者预览版2(LPX13D)打破.当我在其他行上拖动一行时,这些行将消失并变得不再可点击(见下文).我尝试禁用listview的硬件加速,但它没有任何效果.

例

有没有人遇到过同样的问题?任何提示?谢谢 :)

小智 40

我发现了这个问题.它来自这面旗帜.StableArrayAdapter.hasStableId.

它修复了Lollipop上这个视图的所有问题.

@Override
public boolean hasStableIds()
{
    return android.os.Build.VERSION.SDK_INT < 20;
}
Run Code Online (Sandbox Code Playgroud)

  • 你应该使用常量,如下所示:Build.VERSION.SDK_INT <Build.VERSION_CODES.LOLLIPOP(21) (12认同)
  • 这在技术上是错误的.ID是稳定的,它们必须是或系统不起作用. (5认同)

Ant*_*nit 15

说实话,我不是导致问题的原因,但是这个修复程序在任何版本上都不会出现任何视觉错误.因为所有改变的只是视图的可见性,我相信它不应该创造任何新的功能问题.


handleCellSwitch()在类中的函数中替换此代码DynamicListView:

mobileView.setVisibility(View.VISIBLE);
switchView.setVisibility(View.INVISIBLE);
Run Code Online (Sandbox Code Playgroud)

对于

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);
}
Run Code Online (Sandbox Code Playgroud)

我试着修补代码,最后我找到了一种方法,让它像以前一样显示.但是修复Lollipop的问题会导致相同的问题出现在KitKat和以前的版本中.所以我只为高于KitKat的Android版本应用了修复程序.

我的猜测是,由于某种原因,在新的Lollipop版本中,这两个视图在这个过程中被交换.实际上,其中一个视图始终显示,而另一个视图始终隐藏.很高兴知道棒棒糖安卓代码在哪里以及改变了什么......

  • 感谢您的修复,它大部分都有效,但仍然存在故障.将项目拖过列表底部时,列表会自动向下滚动.如果现在向上拖动同一个项目而不释放它,列表会开始向上滚动,但会出现一个空项目. (3认同)

Tat*_*ize 8

正确的解决方案是在回收之前将该视图的可见性重新打开,然后在绘制之前将其关闭.

       ((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);
Run Code Online (Sandbox Code Playgroud)

用...来代替,

        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);
Run Code Online (Sandbox Code Playgroud)

stableid解决方案是错误的.ID是稳定的并且告诉它它们不是错误的.它只是简化了系统,以旧方式回收视图.这实际上是一种糟糕的做法,并在棒棒糖中修复.这是一个更正确的解决方案.给出你正在使用的任何版本,而不是预测.notifyDataSetChanged将如何影响视图以及打开和关闭正确的元素.这个将在所有情况下打开可见性.然后在预绘制侦听器中再次找到视图并在它被绘制之前以及在它处于正确状态之后将其变回不可见.

并且无关紧要,如果该视图是否相同,或者某些未来版本具有某种不同的方式,或者实际上不回收视图的不良适配器等.稳定的ID或不稳定ID(标记不稳定,它们仍然必须实际稳定,但这很容易修复),这是正确地做到这一点并且未来证明的方法.

这里的问题是,您将获得的回收视图实际上并不清楚(毕竟它们是半垃圾回收视图),而不是您可以安全存储属性的内容.Lollipop中的行为已更改以实际保持稳定视图如果可以稳定,你可以检查适配器功能,并且回收的视图可能已经有你的数据,因为它会最大限度地为你提供相同的视图.这是你想要的东西,这就是为什么棒棒糖这样做的原因.

这里的问题是代码说应该使mobileView可见(你正在移动的那个),并且应该使switchView不可见(你正在切换的那个).但是,这些将被回收,因此它们在技术上是模棱两可的,你会得到回报,并完全取决于系统如何回收视图,并且完全允许改变这种行为,并且做到了.

PS.我懒得去检查null,因为我个人在中间点交换视图,如果你恰到好处的话,它有时最终会变为null.

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

...

        boolean isBelow = (belowView != null) && (deltaYTotal > belowView.getTop());
        boolean isAbove = (aboveView != null) && (deltaYTotal < aboveView.getBottom());
Run Code Online (Sandbox Code Playgroud)

  • 实际上,我基本上重写了整个班级。因为它做了很多事情,所以我讨厌将arraylist和view耦合在一起,以及切换所有东西的真正残缺的需求。https://www.youtube.com/watch?v=aae7Kyz3S00 (2认同)