简体   繁体   中英

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>

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.

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.

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.

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;
     }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM