Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 子视图上的OnLongClickListener禁用父视图上的OnTouchListener_Android_User Interface_Ontouchlistener_Onlongclicklistener - Fatal编程技术网

Android 子视图上的OnLongClickListener禁用父视图上的OnTouchListener

Android 子视图上的OnLongClickListener禁用父视图上的OnTouchListener,android,user-interface,ontouchlistener,onlongclicklistener,Android,User Interface,Ontouchlistener,Onlongclicklistener,我有一个AbsoluteLayout,它有一个OnTouchListener。在这个布局中有一个更小的线性布局动态定位。OnTouchListener按预期工作 现在,当我向我的LinearLayout添加LongClickListener时,问题来了。如果触摸触摸到LinearLayout,则禁用我的OnTouchListener,但如果触摸没有触摸到LinearLayout,则仍会触发该功能 我的听众: // listener on parent (AbsoluteLayout) setOn

我有一个
AbsoluteLayout
,它有一个
OnTouchListener
。在这个布局中有一个更小的
线性布局
动态定位。OnTouchListener按预期工作

现在,当我向我的
LinearLayout
添加
LongClickListener
时,问题来了。如果触摸触摸到
LinearLayout
,则禁用我的
OnTouchListener
,但如果触摸没有触摸到
LinearLayout
,则仍会触发该功能

我的听众:

// listener on parent (AbsoluteLayout)
setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.e("LOOOOGING");
        mLinearLayout.getHitRect(mNoteRect);
        mNoteRect.left += mX;
        mNoteRect.top += mY;
        mNoteRect.right = mNoteRect.left + mLinearLayout.getWidth();
        mNoteRect.bottom = mNoteRect.top + mLinearLayout.getHeight();
        if (mNoteRect.contains((int) event.getX(), (int) event.getY())) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                mStartX = (int) event.getX() - mNoteRect.left;
                mStartY = (int) event.getY() - mNoteRect.top;
                return true;
            }
            mX = (int) event.getX() - mStartX;
            mY = (int) event.getY() - mStartY;

            setPadding(mX, mY, 0, 0);
            return true;
        }
        return false;
    }
});

// listener on child (LinearLayout)
mLinearLayout.setOnLongClickListener(new OnLongClickListener() {
    @Override
    public boolean onLongClick(View v) {
        // do something...
        return true;
    }
});

如何将注册了
OnLongClickListener
线性布局
上的触摸委托给家长?

您尝试过类似的方法吗

   // listener on child (LinearLayout)
mLinearLayout.setOnLongClickListener(new OnLongClickListener() {
    @Override
    public boolean onLongClick(View v) {
        AbsoluteLayout.requestFocus();
        //do something else
        return true;
    }
});
据我所知,触摸相当于获得注意力。()

编辑:检查absoluteLayout文档,这可能会有所帮助:。尝试使用它,听起来像是从公共布尔onLongClick(视图v)启动它可能会有所帮助


将触摸屏运动事件向下传递到目标视图,如果它是目标,则传递到此视图。

我必须在我的ontouchlistener中构建自己的长点击行为

private Handler mLongPressHandler = new Handler();

public final Runnable mDoLongPress = new Runnable() {
    public void run() {
        // do something
    }
};

setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        mLinearLayout.getHitRect(mNoteRect);
        mNoteRect.left += mX;
        mNoteRect.top += mY;
        mNoteRect.right = mNoteRect.left + mLinearLayout.getWidth();
        mNoteRect.bottom = mNoteRect.top + mLinearLayout.getHeight();
        if (mNoteRect.contains((int) event.getX(), (int) event.getY())) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                mStartRawX = (int) event.getX();
                mStartRawY = (int) event.getY();
                mStartX = mStartRawX - mNoteRect.left;
                mStartY = mStartRawY - mNoteRect.top;
                mLongPressHandler.postDelayed(mDoLongPress, 1000);
                return true;
            }
            mX = (int) event.getX() - mStartX;
            mY = (int) event.getY() - mStartY;
            if (event.getAction() == MotionEvent.ACTION_MOVE) {
                if ((mStartRawX + 10 < (int) event.getX() || mStartRawX - 10 > (int) event.getX())
                        || (mStartRawY + 10 < (int) event.getY() || mStartRawY - 10 > (int) event.getY())) {
                    mLongPressHandler.removeCallbacks(mDoLongPress);
                }
            }
            if (event.getAction() == MotionEvent.ACTION_UP) {
                mLongPressHandler.removeCallbacks(mDoLongPress);
            }

            setPadding(mX, mY, 0, 0);
            return true;
        }
        return false;
    }
});
private Handler mLongPressHandler=new Handler();
public final Runnable mDoLongPress=new Runnable(){
公开募捐{
//做点什么
}
};
setOnTouchListener(新的OnTouchListener(){
@凌驾
公共布尔onTouch(视图v,运动事件){
mLinearLayout.getHitRect(mNoteRect);
mNoteRect.left+=mX;
mNoteRect.top+=mY;
mNoteRect.right=mNoteRect.left+mLinearLayout.getWidth();
mNoteRect.bottom=mNoteRect.top+mLinearLayout.getHeight();
if(mNoteRect.contains((int)event.getX(),(int)event.getY()){
if(event.getAction()==MotionEvent.ACTION\u向下){
mStartRawX=(int)event.getX();
mStartRawY=(int)event.getY();
mStartX=mStartRawX-mNoteRect.left;
mStartY=mStartRawY-mNoteRect.top;
mLongPressHandler.postDelayed(mDoLongPress,1000);
返回true;
}
mX=(int)event.getX()-mStartX;
mY=(int)event.getY()-mStartY;
if(event.getAction()==MotionEvent.ACTION\u MOVE){
if((mStartRawX+10<(int)event.getX()| | mStartRawX-10>(int)event.getX())
||(mStartRawY+10<(int)event.getY()| | mStartRawY-10>(int)event.getY()){
mLongPressHandler.removeCallbacks(mDoLongPress);
}
}
if(event.getAction()==MotionEvent.ACTION\u UP){
mLongPressHandler.removeCallbacks(mDoLongPress);
}
设置填充(mX、mY、0、0);
返回true;
}
返回false;
}
});

Maragues从onLongClick()发送dispatchTouchEvent()的想法似乎很有希望,但您必须构建一个事件对象来发送到dispatchTouchEvent(),以模拟OnLongClickListener使用的事件

我将其翻转过来,在父视图中截取触摸事件,然后将其转发到子视图。我对父视图进行了子类化,然后添加了以下方法:

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    // this allows us to catch touch events on the list view if a child button is in the same location, then pass them on to child buttons so they can use them, too
    // we don't have to worry about move events because currently none of the child buttons use them
    int touchX = Math.round(event.getX());
    int touchY = Math.round(event.getY());
    Rect touchRect = new Rect(touchX, touchY, touchX, touchY);
    Log.d("onInterceptTouchEvent", "got touch at " + touchRect);
    switch (event.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            for (View cell : ViewUtils.getSubviews(this)) {
                int cellX = Math.round(cell.getX());
                int cellY = Math.round(cell.getY());
                Rect cellRect = new Rect(cellX, cellY, cellX + cell.getWidth(), cellY + cell.getHeight());
                if (Rect.intersects(touchRect, cellRect)) {
                    for (View button : ViewUtils.getSubviews((ViewGroup) cell)) {
                        if (button instanceof ImageButton) {
                            int buttonX = Math.round(button.getX()) + cellX;
                            int buttonY = Math.round(button.getY()) + cellY;
                            Rect buttonRect = new Rect(buttonX, buttonY, buttonX + button.getWidth(), buttonY + button.getHeight());
                            Log.d("onInterceptTouchEvent", "found button at " + buttonRect);
                            if (Rect.intersects(touchRect, buttonRect)) {
                                Log.d("onInterceptTouchEvent", "forward touch to button");
                                button.dispatchTouchEvent(event);
                                break;
                            }
                        }
                    }
                    break;
                }
            }
            break;
    }
    return true;
}
在我的例子中,父视图是ListView,子视图是表单元格中的ImageButton。因此,该代码遍历表格单元格,然后遍历每个单元格中的按钮,以找到与触摸位置匹配的按钮,并将触摸转发到该按钮。我的按钮都是使用OnClickListener或OnLongClickListener的ImageButton,因此我不会转发动作移动事件,但如果需要,您可以转发

下面是上面使用的getSubViews()方法:

public static ArrayList<View> getSubviews(ViewGroup viewGroup) {
    ArrayList<View> subviews = new ArrayList<View>();
    for (int i=0; i<viewGroup.getChildCount(); i++) {
        subviews.add(viewGroup.getChildAt(i));
    }
    return subviews;
}

这并没有真正帮助我:/你的解决方案是有效的,但它并不完美。您的解决方案存在的问题是,在我释放按钮后,会调用mDoLongPress的run()方法。这可能需要超过预定的1000毫秒。长时间单击应该在指定的时间后执行,不多也不少。在您释放按钮后不应该调用它,因为操作将防止这种情况发生。无论如何,我认为目前的API水平应该有更好的解决方案:D
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    this.onTouch(this, event); // send the touch to the onTouch method below
    return false; // then let the touch proceed to child buttons
    // return true = this method and this view's onTouch receives events; return false = this method and children's onTouch receive events; remove this method = only children's onTouch receive events
}

@Override
public boolean onTouch(View v, MotionEvent event) {
    // work with this touch event here
    return false; // then let the touch continue to other applicable views
    // return true = only this view receives events; return false = this view and other applicable views receive events
}