将侦听器传递给Android中的自定义片段

时间:2017-10-05 13:44:04

标签: java android android-fragments fragment

我在我的应用中创建了一个视图寻呼机,并使用了一个扩展Fragment的类。当我创建一个实例时,我可以传递所有元素(图像,文本等)并将其与Bundle一起存储,以便在onCreate中使用它。但我无法在片段中存储按钮的监听器。这是我的班级:

public class RegWizardFragmentInfo extends Fragment {

private static final String IMAGE = "image";
private static final String TEXT = "text";
private static final String BUTTON = "buttonText";
private View.OnClickListener buttonCallBack;

private Button button;
private int image;
private int text;
private int buttonText;


public RegWizardFragmentInfo newInstance(int image, int text, int buttonText, View.OnClickListener callback) {

    RegWizardFragmentInfo fragment = new RegWizardFragmentInfo();
    Bundle bundle = new Bundle();
    bundle.putInt(IMAGE, image);
    bundle.putInt(BUTTON, buttonText);
    bundle.putInt(TEXT, text);
    fragment.setArguments(bundle);
    fragment.setRetainInstance(true);
    return fragment;

}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    super.onActivityCreated(savedInstanceState);
    this.image = getArguments().getInt(IMAGE);
    this.text = (getArguments() != null) ? getArguments().getInt(TEXT)
            : -1;
    this.buttonText = (getArguments() != null) ? getArguments().getInt(BUTTON)
            : -1;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    ViewGroup rootView = (ViewGroup) inflater.inflate(
            R.layout.fragment, container, false);
    //Extract all the views and add the image and texts

    return rootView;

}

那么,如何将我在newInstance中获得的侦听器存储到onCreateView方法的按钮上呢?

感谢您的帮助。

3 个答案:

答案 0 :(得分:8)

您可以在Fragment中使用回调:

public class RegWizardFragmentInfo extends Fragment {

    private Button button;

    private OnClickCallback callback;

    public interface OnClickCallback {
        void onClick();
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        callback = (OnClickCallback) context;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        return super.onCreateView(inflater, container, savedInstanceState);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                callback.onClick();
            }
        });
    }
}

并在您的父Activity

中实施此新界面

答案 1 :(得分:3)

我想你想要用各种不同的听众重用Fragment。所以你的方法并不理想,因为你不能使用Bundle。更好的方法是使用回调设计模式,例如

public class RegWizardFragmentInfo extends Fragment {

    public interface RegWizardCallback {
        void onClick();
    }
}

您的Activity会实现该界面。由于Fragment仅存在于Activity中,因此您可以使用生命周期方法onAttach()从中获取回调实例。它看起来像这样

public class RegWizardFragmentInfo extends Fragment {
    private RegWizardCallback callback;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            callback = (RegWizardCallback) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement RegWizardCallback ");
        }
    }

    public interface RegWizardCallback {
        void onClick();
    }
}

这样你就可以在Button的监听器内调用callback.onClick

答案 2 :(得分:2)

其他答案在onAttach中分配了侦听器。虽然这可行,但它需要调用Activity(而不是匿名类)来实现您的接口。此外,它会强制您将Context中给出的onAttach强制转换为您的界面实例,这可能会导致崩溃并且通常被视为错误形式。您可以改为创建一种方法来在Fragment

中设置侦听器
public class RegWizardFragmentInfo extends Fragment {

    private OnClickListener mListener;

    public interface OnClickListener {
        void onClick();
    }

    /**
     * Call at any time after this fragment has been constructed.
     */
    public void setListener(OnClickListener listener) {
        mListener = listener;
    }

    /* ...other stuff... */
}

我可以想到这种方法有三个缺点:

  1. 每次要实例化Fragment时,都需要调用额外的方法。
  2. 您无法保证随时设置mListener。您可能需要对Fragment代码进行空检查。
  3. 在屏幕旋转等生命周期事件之后,您需要小心确保侦听器保持设置状态。