Mohammed Nasrullah
Mohammed Nasrullah

Reputation: 433

Android call a method on fragment with onClick error

i am populating a set of custom_rows into my listview from baseadapter. And i set the listview in my fragment. I am trying to set android:onClick="openComment to the button which is in my custom_row.xml but the i get the below error

java.lang.IllegalStateException: Could not find method openComment(View) in a parent or ancestor Context for android:onClick attribute defined on view class android.support.v7.widget.AppCompatImageView with id 'open'

In my Fragment i have the method openComment. How do i call the the method from the button click. This is Fragment shows how i call the method.

public class Home extends android.support.v4.app.Fragment implements View.OnClickListener {
....
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    myview = inflater.inflate(R.layout.home, container,false);
    listView = (ListView) myview.findViewById(R.id.activity_main);
return myview;
}
....
....
public void openComment(View v)
{
  //getting the position of clicked row
  final int position = listView.getPositionForView((View) v.getParent());
  System.out,print("button clicked");
}

my custom_row.xml looks like this. it has a textview and a button

<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <Button
            android:id="@+id/open"
            android:onClick="openComment"
            android:layout_width="45dp"
            android:layout_height="45dp"/>
        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
</LinearLayout>

Below is my ListView activity_main.xml

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">

<ListView
    android:id="@+id/custom_list"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
</ListView>

Upvotes: 1

Views: 3330

Answers (4)

Saifur Rahman Mohsin
Saifur Rahman Mohsin

Reputation: 1011

I came across this and even though it’s been over a year since @Kingfisher Phuoc gave the correct answer, I’d like to share my view as well.

However, I dont think it's a good idea to solve this way.

I couldn’t agree more. It isn’t the best practice to write the logic of a button that’s inside a fragment inside the activity containing the fragment rather than the fragment itself. It’s against the Single responsibility principle and it’s a shame that Google designed Android in a way that it prevents developers to make use of best practices.

So how I do it:

Check out JakeWharton’s ButterKnife library. With this you can bind the views.

So in your activity class’ onCreate you do:

// Bind your views here using @BindView(R.id.someview) MyView myView;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ButterKnife.bind(this);
}

and bind the views it contains. Just like that inside the fragment class’ onCreateView you do:

// Bind your views here using @BindView(R.id.someview) MyView myView;
@BindView(R.id.custom_list)
ListView listView;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.main, container, false);
    // Make sure you unbind too as fragments work differently than activities, check the documentation on how.
    ButterKnife.bind(this, view);
    return view;
}

Check out the documentation and you can even find code to simplify your BaseAdapter implementation to connect openComment to OnClick properly rather than defining it in XML.

Upvotes: 1

Kingfisher Phuoc
Kingfisher Phuoc

Reputation: 8200

Actually, you must declare your openComment(View v) function inside your host activity instead of your fragment. You can declare the function inside your activity as below:

public void openComment(View v){
    yourFragment.openComment(v);
}

However, I dont think it's a good idea to solve this way. You should implement onClickListener inside your adapter or your fragment.

Upvotes: 3

Mohammed Aouf Zouag
Mohammed Aouf Zouag

Reputation: 17142

You can do this:

private ListView listView;
private View myview;

...

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    myview = inflater.inflate(R.layout.home, container,false);
    listView = (ListView) myview.findViewById(R.id.activity_main);

    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            // Use the position argument
            if(view.getId() == R.id.open)
                System.out.print("button clicked");
        }
    });

    return myview;
}

And you won't need that :onClick attribute in your XML layout.

Upvotes: 0

Rushi Ayyappa
Rushi Ayyappa

Reputation: 2858

call it from BaseAdapter. like

 Button btn_opencomment=(Button)yourview.findViewById(R.id.open); 

      btn_opencomment.setOnClickListener(new View.OnClickListener() {
    @override
    public void onClick(View v)
   {
  //getting the position of clicked row
      final int position = listView.getPositionForView((View)              
      v.getParent());
      System.out,print("button clicked");
   //this is your method.what ever you have to do onclick of item.write here..
    });
    return yourview;
     }

Upvotes: 0

Related Questions