- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有父 View v extends 线性布局。子项一是 LinearLayout,子项二是 ScrollView。
我想让 MyParent View 拦截垂直 MotionEvent.ACTION_MOVE(仅向下方向,子 scrollview.getScrollY()==0
)并在父 View 中处理它,并且其他 MotionEvent 由 child 处理
这是MyView.xml
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" >
<LinearLayout
android:id="@+id/child_linear>
android:height="50dp"
android:width="50dp">
...something...
</LinearLayout>
<ScrollView
android:id="@+id/child_scrollview>
<LinearLayout/>
</LinearLayout>
</ScrollView>
</merge>
下面是我的代码
public class MyCustomView extends LinearLayout{
public MyCustomView(Context context) {
super(context);
init();
}
private void init(){
setOrientation(LinearLayout.VERTICAL);
LayoutInflater inflater =
(LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.MyView, this, true);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
final int action = event.getAction();
Log.d(log,"onInterceptTouchEvent : "+action);
if (action == MotionEvent.ACTION_CANCEL || action ==
MotionEvent.ACTION_UP) {
mIsBeingDragged = false;
return false;
}
if (action != MotionEvent.ACTION_DOWN && mIsBeingDragged) {
return true;
}
switch (action) {
case MotionEvent.ACTION_MOVE: {
if (isReadyForPull()) {
final float y = event.getY(), x =
event.getX();
final float diff, oppositeDiff, absDiff;
diff = y - mLastMotionY;
oppositeDiff = x - mLastMotionX;
absDiff = Math.abs(diff);
ViewConfiguration config =
ViewConfiguration.get(getContext());
if (absDiff > config.getScaledTouchSlop() &&
absDiff > Math.abs(oppositeDiff) && diff >= 1f) {
mLastMotionY = y;
mLastMotionX = x;
mIsBeingDragged = true;
Log.d(log,"Flag setting");
}
}
break;
}
case MotionEvent.ACTION_DOWN: {
if (isReadyForPull()) {
mLastMotionY = mInitialMotionY = event.getY();
mLastMotionX = event.getX();
mIsBeingDragged = false;
}
break;
}
}
return mIsBeingDragged;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
final int action=event.getAction();
Log.d(log,"onTouchEvent : "+action);
if (event.getAction() == MotionEvent.ACTION_DOWN && event.getEdgeFlags() != 0) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE: {
Log.d(log,"ACTION MOVE RECEIVE");
if (mIsBeingDragged) {
mLastMotionY = event.getY();
mLastMotionX = event.getX();
pullEvent();
return true;
}
break;
}
case MotionEvent.ACTION_DOWN: {
if (isReadyForPull()) {
mLastMotionY = mInitialMotionY = event.getY();
return true;
}
break;
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
if (mIsBeingDragged) {
mIsBeingDragged = false;
if (mState == State.RELEASE_TO_REFRESH ) {
setState(State.REFRESHING);
return true;
}
if (isRefreshing()) {
smoothScrollTo(-mHeaderHeight , null);
return true;
}
setState(State.RESET);
return true;
}
break;
}
}
return false;
}
isReadyForPull()
函数只检查这个
private boolean isReadyForPull(){
return mScrollView.getScrollY()==0;
}
我的代码运行良好。
如果我向下移动我的子 ScrollView ,onInterceptTouchEvent
首先获取 MotionEvent.ACTION_DOWN 并初始化值,然后依次获取 MotionEvent.ACTION_MOVE 如此设置mIsBeingDragged 标记为 true 并返回 true。所以我可以在我的 ParentView 的 onTouchEvent
中处理事件。
否则,如果我向上移动子 ScrollView ,则 onInterceptTouchEvent
返回 false,我的子 ScrollView 获取 MotionEvent 并向下滚动。
这是预期的工作。好。
但是,当我触摸我的子线性布局时,它不起作用!
如果我触摸并拖动我的子线性布局,我的 CustomView 的 onInterceptTouchEvent
获得 MotionEvent.ACTION_DOWN,但无法获得第二个 MotionEvent.ACTION_MOVE .
为什么这不适用于子线性布局?
注意:我测试了几次,知道(默认)可触摸 View 或 View 组(如按钮、 ScrollView 等)适用于我的代码,而(默认)不可触摸 View 或小部件(如 ImageView 、框架布局)不适用于我的代码。
最佳答案
解决方案涉及this回答,因为它是标准 MotionEvent
处理的结果。
在我的代码中,当我触摸子 LinearLayout
时,父 CustomViewGroup
不会拦截 MotionEvent
,因为它返回 false,但是我的 child LinearLayout
也不使用 MotionEvent
,所以 MotionEvent
返回给父级的 onTouchEvent
,而不是onInterceptTouchEvent
。
另一方面,当我触摸我的 child ScrollView
时,无论滚动是启用还是禁用,它都会消耗 MotionEvent
。
==> 我认为是因为 Android 不会再次生成 MotionEvent
直到原始事件被消耗或完成,所以父级 CustomViewGroup
没有通过 onInterceptTouchEvent
获取 ACTION_MOVE
MotionEvent
,而是在 child 没有获取时通过管道传输到 onTouchEvent
'使用 MotionEvent
。
我找到了两个解决方案
强行让我的 LinearLayout
使用 MotionEvent
。只有当子 LinearLayout
没有可触摸的 View
、ViewGroup
或 Widget
时,此解决方案才可用。像这样:
LinearLayout mLinearLayout = (LinearLayout)findViewById(R.id.child_linear);
mLinearLayout.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
在我的 CustomViewGroup
的 onTouchEvent
中处理从子项返回的 MotionEvent
。像这样:(只需在 onTouchEvent
中添加 else if case)。
case MotionEvent.ACTION_MOVE: {
if (mIsBeingDragged) {
mLastMotionY = event.getY();
mLastMotionX = event.getX();
pullEvent();
return true;
}
else if (isReadyForPull()) {
final float y = event.getY(), x = event.getX();
final float diff, oppositeDiff, absDiff;
diff = y - mLastMotionY;
oppositeDiff = x - mLastMotionX;
absDiff = Math.abs(diff);
ViewConfiguration config = ViewConfiguration.get(getContext());
if (absDiff > config.getScaledTouchSlop() && absDiff >
Math.abs(oppositeDiff) && diff >= 1f) {
mLastMotionY = y;
mLastMotionX = x;
mIsBeingDragged = true;
}
}
break;
}
虽然解决方案 1 是针对某些情况的快速解决方案,但解决方案二是最灵活和可靠的。
关于java - 有 subview 时,Android onInterceptTouchEvent 不会执行操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21953833/
我希望我的 ViewPager 仅在使用单指时滑动。所以我扩展了类并像这样实现了 onInterceptTouchEvent: @Override public boolean onIntercept
我有一个顶级 ViewGroup,我称之为 SliderView,我想在其中检测滑动。这主要是可行的,但仍然存在一个奇怪的故障。 SliderView 的本质是覆盖 onInterceptTouchE
在我的代码中,我使用预先确定的 XML 布局在我的 Activity 中生成 View 。我没有以编程方式创建它们,因此我找不到覆盖 onInterceptTouchEvent 方法的方法!有办法做到
抱歉,如果这含糊不清,但有人可以给我一个何时使用 onInterceptTouchEvent() 的例子吗? 我理解这个概念,在父 ViewGroup 中拦截 subview 触摸,但我为什么需要这样
我问这个相当复杂的问题,希望能从您那里得到一些想法。 事情是这样的:我创建了一个自定义 ListView 类,上面那个: public class FolderListView extends Lis
如何在 ListView 中实现自定义 onInterceptTouchEvent(),将滚动优先级分配给 ListView 的子级并尽快当他们滚动时,将其返回给 ListView ?我想优先考虑内部
我有一个覆盖了 onInterceptTouchEvent() 的自定义 ViewGroup。它收到 ACTION_DOWN 但从未收到 ACTION_MOVE。据我了解,除非它返回“true”,否则
为什么ViewGroup的onInterceptTouchEvent只得到ACTION_DOWN?根据文档,只要返回 false,它就应该接收所有事件类型。 http://developer.andr
我有一个带有 View 的 fragment ,其中包含一些可点击的元素(ToggleButtons 和一个 GridView)。 我在 View 上设置了一个 onTouchListener,我用它
我的布局看起来像这样: 我使用了一个包含 llMain 和 scroll 的 RelativeLayout。在 llMain 中,我有另外两个 LinearLayouts:ll1 和 ll2。每个 L
我希望能够在屏幕上的任意位置滑动来调用某个函数。但我在 Linear Layouts 中也有 Buttons,我希望能够点击它们。如果我在 Button 上滑动,我希望 onInterceptTouc
sdk 说: 3、For as long as you return false from this function, each following event (up to and includi
我确实扩展了 NestedScrollView 和 @Override 它的方法:onTouchEvent 和 onInterceptTouchEvent。问题是 super.onTouchEvent
我正在构建一个漫画/日本漫画应用程序,它有一个包含 viewpager 的 Activity 以显示每章中的图像。我希望 ViewPager 在用户在第一页/最后一页滑出边界时开始新的章节。为此,我通
Android中的onInterceptTouchEvent和dispatchTouchEvent有什么区别? 根据android开发者指南,这两种方法都可以用来拦截一个触摸事件(MotionEven
我一直在寻找,但我仍然没有找到任何东西。我试过了 View child = mirecycler.findChildViewUnder(e.getX(), and.getY()); 在我的例子中,它
日志从不记录ACTION_UP 或ACTION_MOVE(我从代码示例中删除以缩短) 这是我的代码的简化版本: public class ProfileBadgeView extends Linea
我有父 View v extends 线性布局。子项一是 LinearLayout,子项二是 ScrollView。 我想让 MyParent View 拦截垂直 MotionEvent.ACTION
我注意到该函数在 Action_down 之后没有中断,然后代码可以运行到 ACTION_MOVE,对吗? @Override public boolean onInterceptTouchEvent
我扩展了 ViewGroup 以创建自定义 View 。 在触摸事件中,当我的第二根手指触摸屏幕时,onInterceptTouchEvent 方法中未检测到 MotionEvent.ACTION_P
我是一名优秀的程序员,十分优秀!