Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a fragment method from an Adapter

I need to call a Fragment method inside my Adapter, but I get an error:

ClassCastException: Main(MainActivity) cannot be cast to PlayPauseClick(Interface)

I implemented my Interface in my Fragment but I still get this error cause a friend already told me that mContext (my Adapter context) cannot be a Fragment.

So how can I solve this problem?

My Fragment method :

private FunDapter<Product> adapter;
private ArrayList<Product> productList;
private ListView lvProduct;

adapter = new FunDapter<>(getActivity(), productList, R.layout.d_layout_list_d, dict);
lvProduct.setAdapter(adapter);

// My method
@Override
public void imageButtonOnClick(View v, int position){
  playPause=(ImageView)v.findViewById(R.id.playPause);
  Product m = productList.get(position);
  playPause.setImageResource(m.getPlayPauseId());
  playPause.setTag(position);
  playPause.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
            int pos = (Integer) v.getTag();
            Product m =(Product) productList.get(pos);
            if (paused) {
            m.setPlayPauseId(R.drawable.ic_pause);
            paused=false;
            }else {
             m.setPlayPauseId(R.drawable.ic_play);
             paused = true;
            }
       }

    });
}

Interface:

public interface PlayPauseClick{
 void imageButtonOnClick(View v, int position);
}

And my Adapter:

public class FunDapter<T> extends BaseAdapter implements Filterable  {

protected List<T> mDataItems;
protected LongExtractor<T> idExtractor;
protected final Context mContext;
private final int mLayoutResource;
private final BindDictionary<T> mBindDictionary;
private FunDapterFilter<T> funDapterFilter;


public FunDapter(Context context, List<T> dataItems, int layoutResource,
                 BindDictionary<T> dictionary) {
  this(context, dataItems, layoutResource, null, dictionary);
}

public FunDapter(Context context, List<T> dataItems, int layoutResource,
                 LongExtractor<T> idExtractor, BindDictionary<T> dictionary) {
    this.mContext = context;
    this.mDataItems = dataItems;
    this.mOrigDataItems = dataItems;
    this.mLayoutResource = layoutResource;
    this.idExtractor = idExtractor;
    this.mBindDictionary = dictionary;

}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {

    View v = convertView;
    final GenericViewHolder holder;
    if (null == v) {
        LayoutInflater vi =
                (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = vi.inflate(mLayoutResource, null);
        holder = new GenericViewHolder();
        holder.root = v;



    holder.playPause=(ImageView)v.findViewById(R.id.playPause); 
    holder.playPause.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ((PlayPauseClick)mContext).imageButtonOnClick(v, position);        
        }
    });


    return v;
}
like image 852
Mehran Avatar asked Jan 04 '23 13:01

Mehran


1 Answers

If you want to define your interface on the Fragment, then you need to explicitly set that onto the Adapter, not rely on the Context to handle that for you because Activity is mContext, not your Fragment.

So, here is your adapter with an interface defined. It gets activated when you click the button.

public class FunDapter<T> extends BaseAdapter implements Filterable  {

    public interface PlayPauseClick {
     void imageButtonOnClick(View v, int position);
    }

    private PlayPauseClick callback;

    ...

    public void setPlayPauseClickListener(PlayPauseClick listener) {
        this.callback = listener;
    }

    ...

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ...
        holder.playPause.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (callback != null) {
                    callback.imageButtonOnClick(v, position);
                }

And in the Fragment, you can implement that interface (aka your callback)

public class YourFragment extends Fragment 
    implements YourAdapter.PlayPauseClick // see here

    // private ... adapter;
    private List<Product> data = new ArrayList<Product>();

    @Override 
    public View onCreateView(...) {
        // Set your adapter
        // Pass the listener here
        this.adapter = new FunDapter<Product>(...); 
        this.adapter.setPlayPauseClickListener(this);
    }

    @Override
    public void imageButtonOnClick(View v, int position) {
        // TODO: Implement this
    }

And you should remove the interface implementation on the Activity class.

like image 113
OneCricketeer Avatar answered Jan 13 '23 12:01

OneCricketeer