11

I have my fragments inside ViewPager and I would like in one of them to have clickable RelativeLayout. I am using data binding:

<data>

        <variable
            name="handlers"
            type="com.matip.presenters.MyPresenter" />
</data>

<RelativeLayout
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:onClick="@{() -> handlers.onLayoutClick()}">

                ...
                ...
                ...

</RelativeLayout>

My Fragments onCreateView:

public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mBind = DataBindingUtil.inflate(inflater, R.layout.fragment_layout, container, false);
        presenter = new MyPresenter();
        mBind.includedLayout.setHandlers(presenter);
        return mBind.getRoot();
    }

But the onLayoutClick is not being called. Does it have something to do with ViewPager? Does it take the click and not the fragment inside it? If so how can I fix that?

EDIT

My ViewPager Adapter:
private class MyViewPagerAdapter extends FragmentStatePagerAdapter {
        public MyViewPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            switch(position) {
                case 0:
                    return MainInfoFragment.newInstance(parkingId);
                case 1:
                    return MainDescFragment.newInstance(parkingId);
                case 2:
                    return MainServicesFragment.newInstance(parkingId);
                default:
                    return null;
            }


        }

        @Override
        public int getCount(){
            return 3;
        }

        @Nullable
        @Override
        public CharSequence getPageTitle(int position) {
            switch(position){
                case 0: return getContext().getString(R.string.info_title);
                case 1: return getContext().getString(R.string.desc_title);
                case 2: return getContext().getString(R.service_title);
                default: return null;
            }
        }
    }
matip
  • 794
  • 3
  • 7
  • 27

4 Answers4

3

To get onClick attribute in XML to be worked, the method need to be in activity. For fragments the preferred method is setting a listener programmatically. The XML method will work if the method is in the activity but it will become complicated if the method need to be behaved differently for different fragments.

Also I don't understand what you mean by android:onClick="@{() -> handlers.onLayoutClick()}". Normally it looks likeandroid:onClick="onLayoutClick". And the definition will be like

public void onLayoutClick(View view) {
    //Your code
} 

There is one more possibility: you might have set an OnTouchListener to the view which overrides the click. If you want both touch and click listeners, then try GestureDetector.

Bertram Gilfoyle
  • 9,899
  • 6
  • 42
  • 67
  • xml 's onClick event must declare in Activity, it use reflection way to find method in Activity. – act262 Jun 12 '18 at 01:17
  • 1
    It doesn't have to be in activity. I am using data binding and providing my presenter class ho handle the clicks. But also using the standard method for handling clicks still doesn't work – matip Jun 12 '18 at 10:07
1

you may do the following on the oncreateview() method

oncreate(....)
{.....
View v = inflater.inflate(R.layout.fragment_layout,container,false);
RelativeLayout l = v.findViewById(R.id.rl);
l.setOnClickListener(this);
.....}

@Override
public void onClick(View v) 
{
     if(v.getId == R.id.rl) 
     {
     //do your work
     }  
}

and change the layout to this

<RelativeLayout
android:id="@+id/rl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
...
...
...
</RelativeLayout>

press alt+enter on the clicklistener if the compiler shows error

Aishik kirtaniya
  • 478
  • 5
  • 19
0

How did you get that includedLayout method from Binding class?
I can't find it anywhere and that was the mistake I got, instead you should just use mBind.setHandlers(presenter);
At first I got error for Binding.setHandler method but after build or running it got solved and worked as expected.
And
Your MyPresenter class should have the exact method signature. for handlers.onLayoutClick() it should be:

public void onLayoutClick(){
....}

There isn't any problem with ViewPager, I tried exactly as yours.
Also check mBind's Type, from your code I guess It should be FragmentLayoutBinding.

Fragment:

public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        FragmentLayoutBinding mBind = DataBindingUtil.inflate(inflater, R.layout.fragment_layout, container, false);
        MyPresenter presenter = new MyPresenter();
        mBind.setHandlers(presenter);
        return mBind.getRoot();
    }

MyPresenter:

public class MyPresenter{

//using listener binding
public void onLayoutClick(){
//do something..
}


//using method reference
public void onButtonClicked(View view){

// do something
}

}

fragment_layout:

<layout...>
<data>

        <variable
            name="handlers"
            type="com.matip.presenters.MyPresenter" />
</data>

<RelativeLayout
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:onClick="@{() -> handlers.onLayoutClick()}">

    <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="32dp"
            android:text="Using Method Ref"
            android:onClick="@{handlers::onButtonClicked}"/>            

</RelativeLayout>
</layout>
Man
  • 2,720
  • 2
  • 13
  • 21
  • that included layout is just layout that is included inside the fragment's main layout – matip Jun 12 '18 at 10:03
  • You don't need to use that includedLayout method, just skip it and use setHanders(presenter) only.. – Man Jun 12 '18 at 10:05
0

Try using the method reference instead of the listener binding notation, your xml will be like this :

android:onClick="@{handlers::onLayoutClick}

And your Presenter will look like this :

public class MyHandlers {
public void onLayoutClick(View view) { ... }
}

/!\ Note that the signature of the method should accept a view as a parameter and return void and be public

EDIT : you can also make sure that none of the childs of the relativeLayout is getting the click instead of him by adding :

android:descendantFocusability="beforeDescendants"
ezzou
  • 2,348
  • 1
  • 15
  • 16