2

So I have simple button in fragment, and I have an exception while clicking it. Fragmens shows up just fine.

Fragment code:

    public void onApplyButtonPressed(View view) {
        System.out.println("Apply button clicked");
//        viewToFilterData();
//        if (mListener != null) {
//            mListener.onFiltersApplyButtonPressed(userData);
//        }
    }

XML layout of fragment

<Button
    android:id="@+id/fragment_filters_apply_button"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:onClick="onApplyButtonPressed"
    android:text="@string/fragment_filters_apply_button" />

And how I attach my fragment in my main activity:

FiltersFragment filtersFragment = FiltersFragment.newInstance(userData);
getSupportFragmentManager().beginTransaction().add(R.id.activity_main_filters_page, filtersFragment).commit();

Can anyone see why this error happens?

 java.lang.IllegalStateException: Could not find method onApplyButtonPressed(View) in a parent or ancestor Context for android:onClick attribute defined on view class android.support.v7.widget.AppCompatButton with id 'fragment_filters_apply_button'
    at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.resolveMethod(AppCompatViewInflater.java:327)
    at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:284)
    at android.view.View.performClick(View.java:4438)
    at android.view.View$PerformClick.run(View.java:18422)
    at android.os.Handler.handleCallback(Handler.java:733)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:136)
    at android.app.ActivityThread.main(ActivityThread.java:5017)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:515)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
    at dalvik.system.NativeStart.main(Native Method)

PS: Using the same method as consumer to View.OnClickListener#onClick(View) works just fine. Something is wrong with method lookup in current context.

Antoniossss
  • 31,590
  • 6
  • 57
  • 99
  • maybe this question help https://stackoverflow.com/questions/6091194/how-to-handle-button-clicks-using-the-xml-onclick-within-fragments – tebitoq Sep 19 '17 at 19:51
  • @tebitoq you are right, I didnt read the post carefully. It says indeed that I cannot reffer to action method in fragment code from xml. – Antoniossss Sep 19 '17 at 20:21

3 Answers3

5

You can not handle the click event in your fragment by refer a method in XML. This only works if the method is implemented in your activity. I think it‘s because the activity ist the context of inflated view but the view doesn‘t have any reference to the fragment.

And this is why the exception is thrown because the method is missing in your activity.

You should use findViewById().setOnClickListener() inside your fragment.

Maik Peschutter
  • 603
  • 4
  • 9
  • [android.view.View](https://developer.android.com/reference/android/view/View.html) which says for android:onClick "Name of the method in this View's context to invoke when the view is clicked. ". The context of the view is definitely the activity. – Maik Peschutter Sep 19 '17 at 20:25
  • This is not correct, you can handle events also in Fragment. You can check example at https://github.com/googlesamples/android-architecture-components. I can confirm that for some reason it does not work all the time. Till now I did not find why. You can check in your generated files(named ...BindingImpl) if you have setOnClickListener in executeBindings. If such is generated it will work file, if not then it defaults to explained search by @MaikPeschutter – Mihail Jan 31 '19 at 09:21
2

The onClick attribute is intended to be used with Activities NOT Fragments. Looks like the using of OnClickListener is the simplest solution in your case. Another option (my favorite) is to use ButterKnife library which allows you to deal with that routine using annotations:

@OnClick(R.id.fragment_filters_apply_button)
void onApplyButtonClick(View view){
//your code
}
Denys Vasylenko
  • 2,135
  • 18
  • 20
  • sure, if you don't forget to bind view inside onCreateView method: ButterKnife.bind(this, view); – Denys Vasylenko Sep 19 '17 at 20:21
  • Or using data binding and bind a OnClickListener as variable in the xml :) I think there a plenty libraries which can handle this in different ways. Using Butterknife just to handle the click event this way is a little misspend. But possible :) – Maik Peschutter Sep 19 '17 at 20:33
  • If you try ButterKnife it will hard to resist use all the features it offers) – Denys Vasylenko Sep 19 '17 at 20:42
0

You inflate fragment from your MainActivity, so it puts in the main layout so the context for your xml is activity that instantiates your fragment. Make sure that you have onApplyButtonPressed(View v)method in your MainActivity.