拖动View之后,内容更新,触发onLayout,View回到原位的解决方法

2016.05.26 10:39 Thu| 224 visits | Text

我们都知道如果使用View Animation来操作view的话,只要为Animation设置setFillEnabled(true)以及setFillAfter(true)即可在动画结束后,保持View的位置。

如果使用v4包中的ViewDragHelper辅助类改变view位置,或者在View的onTouch中计算滑动距离,通过offsetTopAndBottom()改变View位置(其实ViewDragHelper中也是使用同样方法)。这种情况下当有因素触发layout后,View会自动回到初始位置。我们怎么处理呢?

这种现象的原因是由于offsetTopAndBottom等方法的原理是通过改变View的top和bottom等参数来改变View的显示位置。但是刷新时layout方法会根据View的LayoutParams参数重新计算其top、bottom值,导致view“归位”。

我们能想到的第一个方法就是把View的位置改变实时更新到它的LayoutParams中,Google使用ViewDragHelper实现了v4中的DrawerLayout,他们就是这么解决这个问题的。在DrawerLayout中定义了一个LayoutParams内部类,使用这个内部类临时保存了拖动位置的信息。然后通过setDrawerViewOffset()更新View的位置。如果你有多个可拖动View的时候,推荐使用这种方法。

还有一个相对简单的方法:可以为我们的View设置一个OnLayoutChangeListener,在onLayout时,让其回到我们想要的位置。

rlMainView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                if( rlOuterView.isMoving() ){
                    v.setTop(oldTop);
                    v.setBottom(oldBottom);
                    v.setLeft(oldLeft);
                    v.setRight(oldRight);
                }
            }
        });

具体可以看下这个博客,学习下ViewDragHelper的使用。