Accessing onClick form an Android fragment using Navigation

Viewed 958

I cannot set an onClick listener fo my button in a fragment. Maybe i have the context wrong but i cannot see it.

Please help below i think i am doing everything Ok? I though i understood the context working but it seems to me that what works one day does not the next?

fragment xml:

    <?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:background="@color/colorPrimary"
    tools:context=".OBWelcomeFragment">

    <ImageView
        android:id="@+id/imageView3"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:src="@drawable/logo_main"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.08" />

    <ScrollView
        android:id="@+id/scrollView3"
        android:layout_width="324dp"
        android:layout_height="333dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.494"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/imageView3"
        app:layout_constraintVertical_bias="0.594">

        <TextView
            android:id="@+id/tv_description_heading"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="@string/ob_welcome_text"
            android:textColor="@color/cardview_light_background"
            android:textSize="18sp" />

    </ScrollView>

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:text="@string/app"
        android:textColor="@color/cardview_light_background"
        android:textSize="36sp"
        app:layout_constraintBottom_toTopOf="@+id/scrollView3"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/imageView3"
        app:layout_constraintVertical_bias="0.18" />

    <Button
        android:id="@+id/oBlocationButton"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="32dp"
        android:layout_marginLeft="32dp"
        android:layout_marginEnd="32dp"
        android:layout_marginRight="32dp"
        android:layout_marginBottom="32dp"
        android:onClick="onClick"
        android:text="Next"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/scrollView2" />
    </androidx.constraintlayout.widget.ConstraintLayout>

The corresponding fragment

    import android.os.Bundle;

    import androidx.appcompat.app.AppCompatActivity;
    import androidx.fragment.app.Fragment;
    import androidx.fragment.app.FragmentActivity;
    import androidx.navigation.NavDirections;
    import androidx.navigation.Navigation;

    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;


    public class OBWelcomeFragment extends Fragment implements View.OnClickListener {

    public OBWelcomeFragment() {
        // Required empty public constructor
    }

    public static OBWelcomeFragment newInstance(String param1, String param2) {
    OBWelcomeFragment fragment = new OBWelcomeFragment();
    return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_o_b_welcome, container, false);
    }

    @Override
    public void onClick(View v) {

        NavDirections action = 
    OBWelcomeFragmentDirections.actionOBWelcomeFragmentToOBLocationFragment3();
        Navigation.findNavController(v).navigate(action);

    }
    }

The error

    2020-02-27 12:43:50.375 15523-15523/com.app E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.app, PID: 15523
    java.lang.IllegalStateException: Could not find method onClick(View) in a parent or ancestor 
    Context for android:onClick attribute defined on view class 
    androidx.appcompat.widget.AppCompatButton with id 'oBlocationButton'
        at 
androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.resolveMethod(AppCompatView 
    Inflater.java:436)
        at 
androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflat .er.java:393)
        at android.view.View.performClick(View.java:7259)
        at android.view.View.performClickInternal(View.java:7236)
        at android.view.View.access$3600(View.java:801)
        at android.view.View$PerformClick.run(View.java:27892)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

Please let me know if you need anything else?

1 Answers

The problem is you're doing both (both are incomplete though...), implementing the OnClickListener and have defined a method in the xml. Do any one of them.

I'll specify both of those, to do it only in the xml you'll have to specify your onClick() method in the xml not

<Button
    android:id="@+id/oBlocationButton"
    ....
    android:onClick="onClick"/>

In your fragment just create this method: (do not implement the listener)

public class OBWelcomeFragment extends Fragment {

    ....

    // notice -> no override here..
    public void onClick(View v) {


    }
}

Or the other way: this time don't specify onClick in xml, instead just find button and set listener.

public class OBWelcomeFragment extends Fragment implements View.OnClickListener {

    .....

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        Button btn = view.findViewById(R.id.oBlocationButton);
        btn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        NavDirections action = OBWelcomeFragmentDirections.actionOBWelcomeFragmentToOBLocationFragment3();
        Navigation.findNavController(v).navigate(action);
    }
}
Related