Frage

ich eine AbsoluteLayout haben, die eine OnTouchListener hat. Innerhalb dieses Layouts gibt es einen viel kleineren LinearLayout dynamisch positionierte. Die OnTouchListener wie erwartet funktioniert.

Jetzt kommt das Problem, wenn ich ein LongClickListener meinen LinearLayout hinzufügen. Das deaktiviert meine OnTouchListener wenn die Berührung der LinearLayout trifft, aber es ist immer noch ausgelöst, wenn die LinearLayout war nicht Treffer durch Berührung.

Meine Zuhörer:

// 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;
    }
});

Wie kann ich die Berührung auf dem LinearLayout delegieren, wo der OnLongClickListener registriert ist, an die Eltern?

War es hilfreich?

Lösung

Ich hatte mein eigenes longclick Verhalten in meinem ontouchlistener

bauen
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;
    }
});

Andere Tipps

Haben Sie so etwas wie dies versucht?

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

Von dem, was ich gelesen habe, ist Touch-äquivalent Fokus zu gewinnen. ( Umgang UI Ereignisse )

edit: die absoluteLayout Dokumentation Überprüfung, vielleicht könnte dies helfen: dispatchTouchEvent (Motion ev) . Versuchen Sie, mit ihm zu spielen, klingt wie es startet von der public boolean onLongClick (Blick v) könnte helfen,

übergeben Sie das Touch-Screen-Bewegungsereignis bis auf die Zielansicht, oder diese Ansicht, wenn es das Ziel ist.

Maragues Idee dispatchTouchEvent () von onLongClick zu senden () schien vielversprechend, aber man müßte ein Ereignisobjekt baut das Ereignis dispatchTouchEvent (), um Mimik zu senden, die von der OnLongClickListener verbraucht wurde.

blätterte ich diese um zu Intercept des Berührungsereignis in der übergeordneten Ansicht, es dann zu der Ansicht, Kind weiterleiten. Ich subclassed die übergeordnete Ansicht, dann hinzugefügt, um diese Methode:

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

In meinem Fall ist die übergeordnete Ansicht ist ein Listview und das Kind Ansicht sind ImageButtons in den Tabellenzellen. Also dieser Code der Tabellenzellen durchläuft, dann in jeder Zelle der Tasten, eine Taste zu finden, die die Berührungsposition entspricht, und leitete die Verbindung zu dieser Taste. Meine Tasten sind alle ImageButtons die OnClickListener oder OnLongClickListener verwenden, so dass ich nicht ACTION_MOVE Ereignisse, aber man konnte, wenn nötig.

Hier ist das getSubViews () -Methode oben verwendet:

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

Update: Einfachere Version

Der obige Code sollte für die spezifische Situation arbeiten von Berührungen auf einer übergeordneten Ansicht und lange Klicks auf einer untergeordneten Ansicht zu empfangen. Aber ich fand, dass dies nicht regelmäßig Klicks in den Kindern Ansichten unterstützt. Ich denke, dies ist die Art und Weise zusammenhängt, dass onInterceptTouchEvent () Griffe Ereignisse ACTION_DOWN anders als andere Ereignisse behandelt. Die Dokumentation für diese Methode ist sehr verwirrend.

Hier ist jedoch ein einfacher Ansatz, der alle Arten von Touch unterstützen sollten und klicken Sie auf Ereignisse in entweder die Eltern oder das Kind Blick. Wie oben erwähnt, erfordert dies Subklassen der übergeordneten Ansicht. Es erfordert auch die OnTouch Methode direkt in dieser Klasse Einstellung anstatt setOnTouchListener () in einer anderen Klasse:

@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
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top