当前位置: 首页 > 知识库问答 >
问题:

无法在片段[重复]中的RecolyerView中获取onClick事件

姚建树
2023-03-14

我正在使用Json为应用程序获取数据和图像。这些图像显示在RecolyerView中,该View位于连接到MainActivity的片段(Tab1.java)的内部。我想以这样的方式设置它,这样当用户单击RecyclerView中的一个图像时,就启动了一个新的活动(viewImage.java),图像就显示在那里。

到目前为止,我已经能够获取Json数据并将其显示在一个回收器视图中。图像显示得很好,但当我尝试设置“SetItemonClickListener”时,应用程序开始崩溃(我在Tab1.java中用注释标记了这一行)。

表1.Java

/*
 * A simple {@link Fragment} subclass.
 * Activities that contain this fragment must implement the
 * {@link Tab1.OnFragmentInteractionListener} interface
 * to handle interaction events.
 * Use the {@link Tab1#newInstance} factory method to
 * create an instance of this fragment.
 */
public class Tab1 extends Fragment implements CardAdapter.OnItemClickListener{
    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;

    public static final String EXTRA_URL = "imageUrl";

    private RecyclerView mRecyclerView;
    private CardAdapter mCardAdapter;
    private ArrayList<Card> mCardList;

    TextView textView;

    private OnFragmentInteractionListener mListener;

    public Tab1() {
        // Required empty public constructor
    }

    /*
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment Tab1.
     */
    // TODO: Rename and change types and number of parameters
    public static Tab1 newInstance(String param1, String param2) {
        Tab1 fragment = new Tab1();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

//    @Override
    public void onCreate(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

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

        mRecyclerView = v.findViewById(R.id.recycler_view);
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

        mCardList = new ArrayList<>();

        /*
         * Retrofit code to fetch the Json data
         */
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(ApiService.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        ApiService service = retrofit.create(ApiService.class);
        Call<JsonResponse> call = service.getPopulationData();
        final StringBuffer flagData = new StringBuffer();

        call.enqueue(new Callback<JsonResponse>(){
            @Override
            public void onResponse(Call<JsonResponse> call, Response<JsonResponse> response) {
                ArrayList<Worldpopulation> population=new ArrayList(response.body()
                        .getWorldpopulation());

                for (Worldpopulation j : population) {
                    String countryName = j.getCountry();
                    String imageUrl = j.getFlag();
                    int rank = j.getRank();

                    mCardList.add(new Card(imageUrl, countryName, rank));
                }

                mCardAdapter = new CardAdapter(getActivity(), mCardList);
                mRecyclerView.setAdapter(mCardAdapter);

                // This particular line of code is causing the application to crash.
                // And I cannot figure out how this is supposed to be implemented.
                mCardAdapter.setItemOnClickListener((CardAdapter.OnItemClickListener) getContext());

            }

            @Override
            public void onFailure(Call<JsonResponse> call, Throwable t) {
                Log.d("JSONError", t.getMessage());
            }
        });

        // Inflate the layout for this fragment
        return v;
    }

    // TODO: Rename method, update argument and hook method into UI event
    public void onButtonPressed(Uri uri) {
        if (mListener != null) {
            mListener.onFragmentInteraction(uri);
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    @Override
    public void onItemClick(int position) {
        Intent imagePreview = new Intent(getActivity(), ViewImage.class);
        Card clickedItem = mCardList.get(position);

        imagePreview.putExtra(EXTRA_URL, clickedItem.getImageUrl());

        startActivity(imagePreview);
    }

    /*
     * This interface must be implemented by activities that contain this
     * fragment to allow an interaction in this fragment to be communicated
     * to the activity and potentially other fragments contained in that
     * activity.
     * <p>
     * See the Android Training lesson <a href=
     * "http://developer.android.com/training/basics/fragments/communicating.html"
     * >Communicating with Other Fragments</a> for more information.
     */
    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        void onFragmentInteraction(Uri uri);
    }
}

CardAdapter.java

public class CardAdapter extends RecyclerView.Adapter<CardAdapter.CardViewHolder> {
  private Context mContext;
  private ArrayList<Card> mCardList;
  private OnItemClickListener mListener;

  public interface OnItemClickListener {
    void onItemClick(int position);
  }

  public void setItemOnClickListener(OnItemClickListener listener) {
    mListener = listener;
  }

  public CardAdapter(Context context, ArrayList<Card> cardList) {
    mContext = context;
    mCardList = cardList;
  }

  @Override
  public CardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(mContext).inflate(R.layout.card, parent, false);
    return new CardViewHolder(v);
  }

  @Override
  public void onBindViewHolder(CardViewHolder holder, int position) {
    Card currentItem = mCardList.get(position);

    String imageUrl = currentItem.getImageUrl();
    String countryName = currentItem.getCountryName();
    int rank = currentItem.getRank();

    holder.mTextViewCountry.setText(countryName);
    holder.mTextViewRank.setText("Rank: " + rank);

    Picasso.get().load(imageUrl).fit().centerInside().into(holder.mImageView);
  }

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

  public class CardViewHolder extends RecyclerView.ViewHolder {
    public ImageView mImageView;
    public TextView mTextViewCountry;
    public TextView mTextViewRank;

    public CardViewHolder(View itemView) {
      super(itemView);
      mImageView = itemView.findViewById(R.id.image_view);
      mTextViewCountry = itemView.findViewById(R.id.text_view_country_name);
      mTextViewRank = itemView.findViewById(R.id.text_view_rank);

      itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
          if (mListener != null) {
            int position = getAdapterPosition();
            if (position != RecyclerView.NO_POSITION) {
              mListener.onItemClick(position);
            }
          }
        }
      });
    }
  }
}

ViewImage.java

public class viewimage extends appcompatactivity {

  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_view_image);
    // imageview where the image is to be displayed in this activity
    imageview imageview = findviewbyid(r.id.fullscreenimage);

    bundle bundle = getintent().getextras();
    if (bundle != null) {
      string imageurl = bundle.getstring("extra_url");
      if (imageurl != null) {
        picasso.get().load(imageurl).fit().centerinside().into(imageview);
      }
    }
  }
}

共有1个答案

司徒鸿文
2023-03-14

正如您已经知道的,此方法在RecyclerView类中不再可用。

我在RecyclerView中实现OnClick事件的方法如下所示:

class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {

    interface OnClickListener {
        void onClick(Item item);
    }

    private final List<Item> dataset;
    private final OnClickListener l; 

    public MyAdapter(List<Item> data, OnClickListener listener) {
        this.dataset = data;
        this.l = listener;
    }

    @Override MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = //inflate layout
        MyClick click = new MyClick() {
            onClick(int position) {
                if (l != null) {
                    l.onClick(dataset.get(position));
                }
            }
        };
        return new MyViewHolder(click, v);
    }

    static class MyViewHolder {
        final MyClick l;

        public MyViewHolder(MyClick listener, View view) {
            super(view);
            l = listener;
            // inflate views
            view.setOnClickListener(new OnClickListener() {
                if (l != null) {
                    l.onClick(getAdapterPosition());
                }
            });
        }

        interface MyClick {
            void onClick(int position);
        }
    }
}

class MyActivity extends AppCompatActivity {

    @Override void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // set layout
        MyAdapter adapter = new MyAdapter(getData(), new OnClickListener() {
            @Override onClick(Item item) {
                // do stuff with item
            }
        });
    }
}
 类似资料:
  • 问题内容: 我阅读了很多有关片段的文章,但是我仍然对如何做感到困惑。 我有一个MainActivity,它并排显示两个片段。在一个片段中,我有一个按钮,并在该片段的片段布局XML中定义 现在我要实现该方法 我以为必须在FragmentA.java中实现,而不是在MainActivity.java中实现。但是,只有在MainActivity.java中实现了该方法后,该方法才有效。这是为什么?对我而

  • 我在一个xml布局文件中声明了许多按钮,并将此布局用于一个片段。 令人失望的是,“onclickbutton”事件被捕捉在主机activity,而不是在我的片段。当然,在我的片段中,我可以手动解决这个问题,如下所示: 有没有显式的方法来处理片段中的onClickbutton事件?

  • 我得到了这个错误,但我不知道是什么原因导致的...也许是因为它是在一个片段中初始化的,而不是在activity本身。编辑:包含的StatsAdapter代码

  • 我想在收到一些HTTP请求的响应后,更新几个<code>片段 。-- 活动 适配器 碎片样本 日志显示位置0,1处的片段的<code>updateData</code>工作良好。但是对于位置2处的片段,它会导致错误。 我发现的区别是适配器没有为位置2调用,这意味着没有调用的。因此不存在。 我的直觉告诉我,问题一定来自适配器的工作流或fragmentManager事务。但是作为一个Android初学

  • 我有一个包含大量成员的类,我想检查每个成员是否为null。我不想手动添加它,只要运行一个for循环(或类似的东西),每次添加一个字段时,它将遍历所有字段,而不需要“人工”添加。 到目前为止,我可以查看字段,并收到字段的名称(这是我所需要的)。然而,字段上并没有检查其值是否为null的内容。 以下是我目前掌握的情况: - 在此示例中,打印将为: 缺少名称1 缺少名称3

  • 我使用的是onSavedInstanceState()方法,这样在旋转设备后,我的textview就不会丢失它的值,但我会遇到我在活动中提到的崩溃。 以下是我的活动