Activity 中的片段中的片段创建的 RecyclerView 中的 CardView 上的 onClickListener

onClickListener on a CardView in a RecyclerView created by a Fragment in a Fragment in an Activity

这是一个多部分问题。

第一部分:

我正在构建一个应用程序来跟踪本地事件。目前,我有一个包含 RecyclerView 的 Fragment,该 RecyclerView 由 CardView 组成,每个 CardView 代表一个事件。我想要的是能够点击一张卡片并将片段替换为显示有关该卡片事件的更多详细信息的新片段。

我已经搜索 Google 几个小时了,但是 none 所提供的解决方案在我尝试时似乎有效。下面是创建 RecyclerView 适配器的片段 Tab1 的 class。

public class Tab1 extends Fragment {
//RecyclerView
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;

//ProgressDialog
private ProgressDialog pDialog;

// URL to get contacts JSON
private static String url = "removed";

// JSON Node names
private static final String TAG_EVENT = "event";
private static final String TAG_EVENTNAME = "Event Name";
private static final String TAG_LOCATION = "Location";
private static final String TAG_RAINLOCATION = "Rain Location";
private static final String TAG_ORG = "Org";
private static final String TAG_TIME = "Time";
private static final String TAG_RSVP = "RSVP";

// events JSONArray
JSONArray events = null;
private List<Event> eventlist;
private RecyclerView rv;


@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View v =inflater.inflate(R.layout.tab_2,container,false);

    // Calling async task to get json
    new GetEvents().execute();

    return v;
}
public void onViewCreated(View view, Bundle savedInstanceState) {
    mRecyclerView = (RecyclerView) getView().findViewById(R.id.my_recycler_view);
    mRecyclerView.setHasFixedSize(true);
    mLayoutManager = new LinearLayoutManager(getActivity());
    mRecyclerView.setLayoutManager(mLayoutManager);
}

private class GetEvents extends AsyncTask<Void, Void, Void> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        // Showing progress dialog
        pDialog = new ProgressDialog(getActivity());
        pDialog.setMessage("Please wait...");
        pDialog.setCancelable(false);
        pDialog.show();

    }

    @Override
    protected Void doInBackground(Void... arg0) {
        // Creating service handler class instance
        ServiceHandler sh = new ServiceHandler();

        // Making a request to url and getting response
        String jsonStr = sh.makeServiceCall(url, ServiceHandler.GET);

        Log.d("Response: ", "> " + jsonStr);

        if (jsonStr != null) {
            try {
                eventlist = new ArrayList<>();
                JSONObject jsonObj = new JSONObject(jsonStr);

                // Getting JSON Array node
                events = jsonObj.getJSONArray(TAG_EVENT);

                // looping through All Events
                for (int i = 0; i < events.length(); i++) {
                    JSONObject c = events.getJSONObject(i);

                    String eventName = c.getString(TAG_EVENTNAME);
                    String location = c.getString(TAG_LOCATION);
                    String rain = c.getString(TAG_RAINLOCATION);
                    String org = c.getString(TAG_ORG);
                    String time = c.getString(TAG_TIME);

                    SimpleDateFormat format = new SimpleDateFormat("EEE, MMM d, h:mm a", Locale.US);
                    SimpleDateFormat parserSDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
                    try {
                        Date date = parserSDF.parse(time);
                        time = format.format(date);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }

                    String rsvp = c.getString(TAG_RSVP);

                    eventlist.add(new Event(eventName, time.toUpperCase(), location, R.drawable.pace));
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        } else {
            Log.e("ServiceHandler", "Couldn't get any data from the url");
        }

        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
        // Dismiss the progress dialog
        if (pDialog.isShowing())
            pDialog.dismiss();

        RVAdapter adapter = new RVAdapter(eventlist);
        mRecyclerView.setAdapter(adapter);
    }
}
}

这是 RVAdapter

public class RVAdapter extends RecyclerView.Adapter<RVAdapter.EventViewHolder> {

public static class EventViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    CardView cv;
    TextView eventName;
    TextView eventTime;
    TextView eventLocation;
    ImageView orgPhoto;
    private ClickListener clickListener;


    EventViewHolder(View itemView) {
        super(itemView);
        cv = (CardView)itemView.findViewById(R.id.cv);
        eventName = (TextView)itemView.findViewById(R.id.event_name);
        eventTime = (TextView)itemView.findViewById(R.id.event_time);
        eventLocation = (TextView)itemView.findViewById(R.id.event_location);
        orgPhoto = (ImageView)itemView.findViewById(R.id.org_photo);
        itemView.setOnClickListener(this);
    }

    public interface ClickListener {

        /**
         * Called when the view is clicked.
         *
         * @param v view that is clicked
         * @param position of the clicked item
         */
        public void onClick(View v, int position, String title);

    }

    /* Setter for listener. */
    public void setClickListener(ClickListener clickListener) {
        this.clickListener = clickListener;
    }

    @Override
    public void onClick(View v) {
        clickListener.onClick(v, getPosition(), eventName.getText().toString());
    }
}

List<Event> events;

RVAdapter(List<Event> events){
    this.events = events;
}

@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
    super.onAttachedToRecyclerView(recyclerView);
}

@Override
public EventViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.event_card, viewGroup, false);
    EventViewHolder pvh = new EventViewHolder(v);
    return pvh;
}

@Override
public void onBindViewHolder(EventViewHolder EventViewHolder, final int i) {
    EventViewHolder.eventName.setText(events.get(i).name);
    EventViewHolder.eventTime.setText(events.get(i).time);
    EventViewHolder.eventLocation.setText(events.get(i).location);
    EventViewHolder.orgPhoto.setImageResource(events.get(i).orgPhoto);

    EventViewHolder.setClickListener(new EventViewHolder.ClickListener() {
        @Override
        public void onClick(View v, int pos, String title) {
           //onClick
        }
    });
}

@Override
public int getItemCount() {
    return events.size();
}
}

你可以看到我已经尝试实现接口和onClickListener。 这是正确的方法吗?我尝试通过点击卡片的名称来敬酒来测试它,但它似乎没有用,或者至少敬酒没有出现。

第二部分:

如果这是正确的方法并且应该有效,where/how我是否要编写代码以将片段替换为显示有关事件的更多信息的新片段?它可以进入适配器 class 吗? Tab1 片段实际上位于 activity 内的另一个片段内。我想替换 Tab1 的父片段。

看看这是否有帮助

public class RVAdapter extends RecyclerView.Adapter<RVAdapter.EventViewHolder> {

public static class EventViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    CardView cv;
    TextView eventName;
    TextView eventTime;
    TextView eventLocation;
    ImageView orgPhoto;


    EventViewHolder(View itemView) {
        super(itemView);
        cv = (CardView) itemView.findViewById(R.id.cv);
        eventName = (TextView) itemView.findViewById(R.id.event_name);
        eventTime = (TextView) itemView.findViewById(R.id.event_time);
        eventLocation = (TextView) itemView.findViewById(R.id.event_location);
        orgPhoto = (ImageView) itemView.findViewById(R.id.org_photo);
    }

    @Override
    public void onClick(View view) {
        //do stuff
    }
}

List<Event> events;

RVAdapter(List<Event> events){
    this.events = events;
}

@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
    super.onAttachedToRecyclerView(recyclerView);
}

@Override
public EventViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.event_card, viewGroup, false);
    return new EventViewHolder(v);
}

@Override
public void onBindViewHolder(EventViewHolder EventViewHolder, final int i) {
    EventViewHolder.eventName.setText(events.get(i).name);
    EventViewHolder.eventTime.setText(events.get(i).time);
    EventViewHolder.eventLocation.setText(events.get(i).location);
    EventViewHolder.orgPhoto.setImageResource(events.get(i).orgPhoto);

}

@Override
public int getItemCount() {
    return events.size();
}
}

对于你问题的第二部分。最好让同时托管 Frag1 和 Frag2 的 ParentActivity 切换片段。所以在 ParentActivity 中,有一个框架布局 (R.id.container) 托管 Frag1。

您可以将事件回调传递回 activity,您可以这样做来替换容器中的片段

getSupportFragmentManager()
    .beginTransaction()
    .replace(R.id.container, Frag2)
    .commit();