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
}