Вопрос

у меня есть AbsoluteLayout который имеет АН OnTouchListener. Отказ Внутри этого макета есть гораздо меньше LinearLayout Расположен динамически. OntouchListener работает как ожидалось.

Теперь проблема приходит, когда добавляю LongClickListener к моему LinearLayout. Отказ Который отключает мой OnTouchListener Если прикосновение попадает в LinearLayout, но это все еще вызвано, если 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;
    }
});

Как я могу делегировать связь на LinearLayout где OnLongClickListener зарегистрирован, для родителя?

Это было полезно?

Решение

Я должен был построить свой собственный поведение в длину в моем 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;
    }
});

Другие советы

Вы пробовали что-то вроде этого?

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

Из того, что я прочитал, прикосновение эквивалентно получению фокуса. (Обработка мероприятий UI)

Редактировать: Проверка документации Absolutelayout, может быть, это может помочь: DispatchTouchEvent (MotionEvent EV). Отказ Попробуйте играть с этим, звучит как запуск его из Общественный булевой OnlongClick (View V) может помочь

Передайте событие движения сенсорного экрана до целевого представления, или это представление, если это цель.

Идея Maragues отправить DispatchTouchEvent () из OnlongClick (), казалось, многообещающим, но вам придется построить объект событий для отправки диспетчера (), чтобы имитировать событие, которое было потреблено в OnlongClickLickLickLicklistener.

Я перевернул это, чтобы перехватить сенсорное событие на родительском представлении, а затем переслать его до ребенка. Я подклассул родительский вид, затем добавил этот метод:

@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;
}

В моем случае родительский вид - это список просмотров, а дочерние представления являются ImageButtons внутри клеток в таблице. Таким образом, этот код илетет через ячейки таблицы, то кнопки в каждой ячейке, чтобы найти кнопку, которая соответствует сенсорному расположению, и пересылает прикосновение к этой кнопке. Мои кнопки - это все ImageButtons, которые используют OnClickListener или OnlongClickLickListener, поэтому я не пересылаю события Action_Move, но вы можете при необходимости.

Вот метод 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;
}

Обновление: проще версия

Код выше должен работать на определенную ситуацию приема прикосновения на родительском виду и длинных щелчках на дочернем виде. Но я обнаружил, что это не поддерживает регулярные клики в дочерних взглядах. Я думаю, что это связано с тем, как oniternectTechevent () обрабатывает события dave_down иначе, чем она обрабатывает другие события. То Документация для этого метода очень запутанно.

Тем не менее, вот более простой подход, который должен поддерживать всевозможные сенсорные и щелкнуть событиями в родительском или дочернем представлении. Как указано выше, это требует подклассов родительского вида. Это также требует установки метода OnTouch непосредственно в этом классе, а не с использованием SetOntouchListener () в другом классе:

@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
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top