从适配器中调用片段方法

5

我需要在我的适配器中调用一个Fragment的方法,但是我遇到了一个错误:

ClassCastException: Main(MainActivity)无法转换为PlayPauseClick(Interface)

我已经在我的Fragment中实现了接口,但我仍然会遇到这个错误,因为有朋友告诉我,mContext(我的适配器上下文)不能是一个Fragment

那么我该如何解决这个问题呢?

我的Fragment方法:

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

    });
}

接口:

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

我的适配器:

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

你在你的活动中实现了接口吗? - rafsanahmad007
2个回答

10

如果你想在Fragment上定义接口,那么你需要明确地将其设置到Adapter上,而不是依赖于Context来处理,因为ActivitymContext,而不是你的Fragment。

所以,这是你的适配器,并定义了一个接口。当你点击按钮时它就会被激活。

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

在 Fragment 中,您可以实现该接口(也就是您的回调函数)。

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
    }

你应该从Activity类中删除接口实现。


0
你看到的错误是因为 mContext 是一个 Activity 而不是你的 PlayPauseClick。我建议你这样做:
1)在创建 Fragment 时给它一个标签并将其保存在 Activity 中:
    MyFragment fragment = new MyFragment();
    final FragmentManager fm = getFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    View containerView = getContainerView();
    ft.add(containerView.getId(), fragment, tag);

2) 在适配器内执行以下操作:

holder.playPause.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        FragmentManager fm = ((MyActivity)mContext).getFragmentManager();
        final MyFragment dismissedFragment = (MyFragment)fm.findFragmentByTag(((MyActivity)mContext).getMyFragmentTag());
        dismissedFragment.imageButtonOnClick(v, position);        
    }
}

1
你是如何在适配器中调用getFragmentManager的? - OneCricketeer
@cricket_007 你是对的,getFragmentManager() 需要 activity。我已经修复了代码以反映这一点。 - Doron Yakovlev Golani
1
MyActivity强制转换为类型会将适配器与Activity耦合在一起,这可能不是最好的设计。 - OneCricketeer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接