我在我的游戏中实现了一个自定义的可扩展动作栏。我使用ViewDragHelper来处理栏视图的拖动和投掷,它包含在我子类化的LinearLayout
中,以附加ViewDragHelper。
以下链接对实现这一目标有很大帮助:
- ViewDragHelper教程:http://flavienlaurent.com/blog/2013/08/28/each-navigation-drawer-hides-a-viewdraghelper/
- 掌握Android触控系统:https://www.youtube.com/watch?v=EZAoJU-nUyI(这给了我使视图可点击和可拖动的关键)
我遇到的唯一问题是父LinearLayout的layout()的行为:在每次调用layout()
/onLayout()
时,子可拖动/可扩展操作栏重置到其原始位置(在XML布局中设置的位置)。
为什么
(In我的经验layout()
从来没有弄乱已经移动的视图的位置)
6条答案
按热度按时间yzxexxkh1#
我使用的解决方法是在每次拖动操作之后记录视图的偏移量,并在
onLayout()
中重新应用它们,例如。v8wbuo2f2#
我在玩DrawerLayout(一种具有可拖动抽屉的布局)时遇到了同样的问题,最初也很惊讶。
从阅读源代码来看,ViewDragHelper似乎使用了offsetLeftAndRight()/ offsetTopAndBottom()来可视化地移动任何捕获和拖动的视图,大概可以使用到API 4。
回答您的问题:布局并没有扰乱视图的位置,只是通过使用offset..()函数,ViewDragHelper并没有为您确定视图的位置。
因此,在视图的onLayout中,您必须考虑使用ViewDragHelper完成的任何视觉定位。例如,在DrawerLayout中,这是通过一个简单的'lp.onScreen'百分比字段进行内部跟踪的,并且在其onLayout()中,相应的移位被添加到任何拖动的抽屉子视图的child.layout()调用中的参数中。
mwyxok5s3#
对不起,我不知道为什么layout()被调用,但也许你的视图之一,如ViewPager调用getView(View parentView)。
无论如何,我假设你使用的是像this blog描述的DragViewHelper。所以有一个相关的方法 OnLayoutChangeListener 将布局移动到前一个位置。
因此,当调用layout()时,方法isMoving应该被启动-但它看起来并没有。因为DragViewHelper处于STATE_IDLE状态。我感谢user3452758的回答技巧。您需要在方法computeScroll()中设置自定义滑动布局中的标志,以便在正确的时间启用isMoving == true。
zdwk9cvp4#
这个答案有点晚了,但是当requestLayout()被调用时,你的内容被中继到它的原始位置的原因是(很可能)因为你在onLayout()中的代码没有考虑到视图位置的变化。
在flavienlaurent示例中,他的布局代码将可拖动视图定位在左侧位置0,但顶部位置使用全局作用域变量mTop,该变量在回调onViewPositionChanged(android.view.View,int,int,int,int)中修改为top值。您需要跟踪更改的值并将其纳入onLayout()中。
将位置更改与拖动视图绑定在一起的一种简单方法是将它们存储在LayoutParams中,并在布局代码中检索主题。如果您希望在布局中有多个可拖动的视图,这一点尤其有用。此模式的一个很好的示例是Android SDK DrawerLayout的source code(NavigationDrawer)。看一下类的底部,在自定义LayoutParams内部类。它有一个类型为float的onScreen字段。此变量用于存储位置差异(相对于视图原点),并在setDrawerViewOffset()中更新。
另一种模式是执行user@user3452758建议的操作,但是如果您希望有多个可拖动的视图,这将很难跟踪。
toiithl65#
你只需要添加这样的代码:
hfwmuf9z6#
1、在viewDragHelper中,记录更改时的pos
int父视图,在onLayout之前设置子位置