2


I have an activity formed by a linear layout with four buttons as children; the layout covers the whole screen size, the buttons cover only half screen size (see here).

Each button has a touch listener so I am able to handle touch events on all buttons at the same time: if, for example, I touch and hold button 1 and after I touch button 2 then button 2 onTouch event is reached even if button 1 was not released.

The problem arise when I touch and hold the background (the linear layout) and, at the same time, I touch one of the buttons: onTouch event does not reach the buttons; I have to release the touch on the background to make buttons works properly.

My needing is to hold the phone with the left hand on the background and to press buttons with the right hand.

How can I make it work?

Edit. As suggested more detail below.

Activity code, assign listeners to buttons. Listener code is not relevant, in the bad case the onTouch method is not reached at all.

    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_keyboard);

    // Setup keyboard listener
    KeyListener keyListener = new KeyListener();
    findViewById(R.id.key_frst).setOnTouchListener(keyListener);
    findViewById(R.id.key_scnd).setOnTouchListener(keyListener);
    findViewById(R.id.key_thrd).setOnTouchListener(keyListener);
    findViewById(R.id.key_frth).setOnTouchListener(keyListener);

}

Activity configuration, in this try there is a ConstraintLayout containing a CustomLinearLayout (see code below) containing four buttons.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clickable="false"
    android:focusable="auto"
    android:focusableInTouchMode="false"
    tools:context=".KeyboardActivity">

    <com.unimi.lim.hmi.ui.CustomLinearLayour
        android:id="@+id/keyboard_vlayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginStart="100dp"
        android:clickable="false"
        android:orientation="vertical"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">

        <Button
            android:id="@+id/key_frth"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:text="@string/key_frth" />

        <Button
            android:id="@+id/key_thrd"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:text="@string/key_thrd" />

        <Button
            android:id="@+id/key_scnd"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:text="@string/key_scnd" />

        <Button
            android:id="@+id/key_frst"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:text="@string/key_frst"
            tools:visibility="visible" />
    </com.unimi.lim.hmi.ui.CustomLinearLayour>

</androidx.constraintlayout.widget.ConstraintLayout>

CustomLinearLayout extends LinearLayout, below the only override method: I tried to always delegate touch events to layout child

    @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    // Always delegate events to child
    return false;
}

Thank you, Daniele

Cheticamp
  • 61,413
  • 10
  • 78
  • 131
  • To help us help you, can you provide some code to show what you are doing to assign the touch listeners currently? – RedBassett Feb 28 '20 at 17:10
  • There is not enough information in this post for you to get a good answer. We need to see what you have tried, what has worked, what has not worked, and any errors you get. Please see this [Link](https://stackoverflow.com/help/how-to-ask) on how to ask a good question so you get better answers. – Edney Holder Feb 28 '20 at 17:15
  • You added clickable="false" to the LinearLayout, try also adding focusable="false" – DevJZ Feb 28 '20 at 19:29
  • Thank you @DevJZ I have tried but it doesn't work. – Daniele Adriano Feb 29 '20 at 16:25

1 Answers1

1

When the LinearLayout is touched directly (outside of its children), the LinearLayout consumes all subsequent touches in the stream and does not offer them to its children even if a finger is dragged over a child. This is regardless of the value returned by onInterceptTouchEvent(). This makes sense because the child would not have seen the original MotionEvent.ACTION_DOWN event.

When the LinearLayout is touched outside of its children then a second finger (pointer) touches a child, the LinearLayout still consumes the subsequent actions. This also makes sense since the second touch could be part of a gesture on the LinearLayout.

The foregoing is all by default. The behavior can be changed by coding the dispatchTouchEvent() in the custom LinearLayout to dispatch the touch on the child to the child by calling the child's dispatchTouchEvent() for the second pointer. (This could also be done in the Activity if you don't want a custom view.)

I have found this helpful in understanding Android's touch system.

Cheticamp
  • 61,413
  • 10
  • 78
  • 131
  • Thank you very much, I empirically noticed that behaviour but I was not able to find it clearly explained. As workaround I created a disabled button at the same hierarchy of other buttons so I am able to grab the phone via this button without consuming other events. I will try to override dispatchTouchEvent(). – Daniele Adriano Feb 29 '20 at 10:45