11

I am currently trying to set a click listener to a LinearLayout view in the .xml layout file using data binding.

I have managed to get it to work well on other views like a Button or TextView, but for some reason it is not working with a LinearLayout.

This is the bare bones of my attempts and I still cannot get it to work:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="72dp"
    android:clickable="true"
    android:focusable="true"
    android:onClick="@{action::linearLayoutClicked}"
    android:orientation="vertical">
</LinearLayout>

Where linearLayoutClicked is my method defined in the action class:

public void linearLayoutClicked(View view) {
    // specific logic
}

I have also tried with child views and those child views with clickable and focusable set to false as well as duplicateParentState set to true and false.

That action is exactly the same action that is being used on other views which is working correctly.

Is this a bug or am I doing this incorrectly? Why is this not working for LinearLayout but works without any problems for other views?

Shadow
  • 4,168
  • 5
  • 41
  • 72
  • Ignore data binding for the moment. If you remove the `android:onClick()` attribute, and you call `setOnClickListener()` on your `LinearLayout`, do you get the results that you want? – CommonsWare Mar 30 '18 at 18:15
  • @CommonsWare Yes, in-code click listener works correctly on the `LinearLayout`. – Shadow Mar 30 '18 at 18:18
  • Hmmm... you might consider looking at the code that gets generated by data binding and see what's in there when you have your `android:onClick` attribute in place. What you have should be OK, though the combination that you're trying (event handler registered via data binding on a non-interactive `View`) may not have been thoroughly tested. – CommonsWare Mar 30 '18 at 18:21
  • use `android:onClick="linearLayoutClicked"` instead of `android:onClick="@{action::linearLayoutClicked}"` i tried and its working – akhilesh0707 Mar 30 '18 at 18:22
  • The generated bindings file shows the same structure set for the other working views, there isn't anything different other than the view type. – Shadow Mar 30 '18 at 18:22
  • Try adding android:clickable=true to the LinearLayout. A wild guess, have not tried myself –  Mar 30 '18 at 18:23
  • 1
    @Thomas Read my sample, it is already using that attribute with that value. – Shadow Mar 30 '18 at 18:24
  • @Shadow read my previous comment it will solve your problem – akhilesh0707 Mar 30 '18 at 18:26
  • Sorry, was too focussed on the discussion. Sorry. –  Mar 30 '18 at 18:26
  • @akhilesh0707 I doubt what you said, I just tried and the app crashes due to `Could not find method linearLayoutClicked` – Shadow Mar 30 '18 at 18:26
  • @Shadow you defined `linearLayoutClicked` method inside your activity right? because i tried and its working – akhilesh0707 Mar 30 '18 at 18:28
  • @akhilesh0707 No, it is a fragment, not an Activity. Now it makes sense why it works for you and not for me. However, thanks to this rubber banding I managed to find what the problem was and fix it. It finally works after 3 days of trying! – Shadow Mar 30 '18 at 18:30

3 Answers3

21

You can handle any view click event like below:

  1. Create interface for handle click event like below:

    interface OnClickHandlerInterface {
        void onClick(View view)
    }
    
  2. Implement that click listener in action class as shown below:

    class MainActivity implements OnClickHanderInterface{
        @Override
        void OnClick(View view){
        }
    }
    
  3. Now bind this interface in XML file:

    <data>
        <variable
            name="clickHandler"
            type=".OnClickHandlerInterface" />
    </data>
    
  4. Now register this interface in action class with use of binding object:

    mActivityMainBinding.clickHandler = this
    
  5. Now set onClick on any which you want to set click listener. For you it's LinearLayout:

    <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="match_parent"
        android:layout_height="72dp"
        android:clickable="true"
        android:focusable="true"
        android:onClick="@{(v)-> clickHandler.onClick(v)}"
        android:orientation="vertical">
    </LinearLayout>
    
  6. Now handle click when your linearLayout clicked you can get click on interface which is implemented in action class:

    @Override
    void OnClick(View view){
        switch(view.getId()){
        case R.id.linearLayout:
            // Handler click and do some actions
            break;
        }
    }
    
  7. As mentioned above you can get layout click by data binding.

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Sagar Kacha
  • 8,338
  • 4
  • 18
  • 27
3

So everything was set up correctly and the generated bindings file shows the click listener being set up correctly, but for some very odd reason half the bindings were working and the newer ones weren't. By newer ones meaning the LinearLayout and all the attempts around it.

What solved the problem was a simple cache invalidation and respective restart and voila, the click listener is working perfectly on the LinearLayout. Just remember to set it clickable and focusable and any child views set as not clickable so they don't consume the event before the parent.

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Shadow
  • 4,168
  • 5
  • 41
  • 72
0

If Invalidate Cache does not work.

then Rebuild project from Build>Rebuild. Fix errors if any then Rebuild again.

Khemraj Sharma
  • 57,232
  • 27
  • 203
  • 212