在 RecyclerView 项目上添加多个 onClickListener

Posted

技术标签:

【中文标题】在 RecyclerView 项目上添加多个 onClickListener【英文标题】:add multiple onClickListeners on RecyclerView items 【发布时间】:2021-01-04 21:09:37 【问题描述】:

我在回收站视图中的 itemView 上添加了一个新活动,但我想在单个项目上添加多个活动。这些教程对 Button 来说非常好,但我不知道如何在 itemview 上实现。 MainActivity中调用的recyclerview如下;

private String[] channelnames="PTC Punjabi","Chakde TV","T-Series Punjabi", "9X Tashan", "Zee Punjabi" ;
    private int[] channelimages=R.drawable.ptcpunjabi, R.drawable.chakde, R.drawable.tseries, R.drawable.ninex, R.drawable.zeepunjabi;
    private List<channel> channelList=new ArrayList<>();

 thirdrecyclerView=findViewById(R.id.third_recycler_view);
        thirdrecyclerView.setHasFixedSize(true);
        channelList=new ArrayList<>();
        LinearLayoutManager thirdlinearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
        thirdrecyclerView.setLayoutManager(thirdlinearLayoutManager);
        for (int i=0;i < channelnames.length;i++)
            channel channel=new channel(channelnames[i],channelimages[i]);
            channelList.add(channel);
        

适配器和viewholder类定义为;

public class channeladpater extends RecyclerView.Adapter<channeladpater.Channelviewholder> 
    private List<channel> channelList;
    Context ctx;

    public channeladpater(List<channel> channelList) 
        this.channelList = channelList;
        this.ctx=ctx;
    

    @NonNull
    @Override
    public Channelviewholder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) 
        View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.card_view,parent,false);
        return new Channelviewholder(view);
    

    @Override
    public void onBindViewHolder(@NonNull Channelviewholder holder, int position)
    
        channel channel=channelList.get(position);
        holder.channelname.setText(channel.getChannelname());
        holder.channelimage.setImageResource(channel.getChannelimage());

        holder.setItemClickListener(new ItemClickListener() 
            @Override
            public void onItemClickListener(View v, int position) 
                Intent intent=new Intent(ctx, MainActivity2.class);
                ctx.startActivity(intent);

            
        );

    

    @Override
    public int getItemCount() 
        return channelList.size();
    

    public static class Channelviewholder extends RecyclerView.ViewHolder implements View.OnClickListener
        public TextView channelname;
        public CircleImageView channelimage;
        ItemClickListener itemClickListener;

        Channelviewholder(@NonNull View itemView) 
            super(itemView);
           this.channelname=itemView.findViewById(R.id.profile_name);
            this.channelimage=itemView.findViewById(R.id.profile_image);
            itemView.setOnClickListener(this);
        

        @Override
        public void onClick(View v) 

            this.itemClickListener.onItemClickListener(v,getLayoutPosition());


        
        public void setItemClickListener(ItemClickListener ic)
            this.itemClickListener=ic;
        
    

在这里,我想将第一个图像或文本视图 (PTC punjabi/R.drawable.ptcpunjabi) 分配给 MainActivity 2,将第二个文本视图和图像视图 (Chakde Tv/R.drawable.chakde) 分配给 MainActivity 3,依此类推。当单击整张卡片时,如何调用文本或图像视图组合到下一个活动开始。 MainActivity 2如下;

public class MainActivity2 extends AppCompatActivity 

        RecyclerView recyclerView;
        ArrayList<VideoDetails> videoDetailsoArrayList;

        Intent intent=getIntent();

        String API_Key = "  ";
        String url="https://www.googleapis.com/youtube/v3/search?part=snippet&channelId="+channelID+"&maxResults=50&sort=date&key=[API_KEY]";
        com.currentmedia.punjabinews.adapter adapter;
        Context ctx;


        @Override
        protected void onCreate(Bundle savedInstanceState) 
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main2);

            recyclerView=findViewById(R.id.listView);
            videoDetailsoArrayList= new ArrayList<>();
            adapter=new adapter(MainActivity2.this,videoDetailsoArrayList);

            displayVideos();

        


        private void displayVideos ()
        
            RequestQueue requestQueue= Volley.newRequestQueue(this);
            StringRequest stringRequest=new StringRequest(Request.Method.GET, url, new Response.Listener<String>() 


                @Override
                public void onResponse(String response) 
                    try 
                        JSONObject jsonObject = new JSONObject(response);
                        JSONArray jsonArray = jsonObject.getJSONArray("items");
                        for (int i = 0; i < jsonArray.length(); i++) 
                            JSONObject jsonObject1 = jsonArray.getJSONObject(i);
                            if (jsonObject1.has("id"))
                                JSONObject jsonVideoId=jsonObject1.getJSONObject("id");
                                if (jsonVideoId.has("kind"))
                                    if(jsonVideoId.getString("kind").equals("youtube#video"))
                                        JSONObject jsonObjectSnippet = jsonObject1.getJSONObject("snippet");
                                        JSONObject jsonObjectDefault=jsonObjectSnippet.getJSONObject("thumbnails").getJSONObject("medium");

                                        String video_id=jsonVideoId.getString("videoId");

                                        VideoDetails vd=new VideoDetails();

                                        vd.setVideoId(video_id);
                                        vd.setTitle(jsonObjectSnippet.getString("title"));
                                        vd.setDescription(jsonObjectSnippet.getString("description"));
                                        vd.setUrl(jsonObjectDefault.getString("url"));

                                        videoDetailsoArrayList.add(vd);
                                    
                                    //  recyclerView.setAdapter(adapter);
                                    // adapter.notifyDataSetChanged();
                                
                            
                        
                    catch (JSONException e) 
                        e.printStackTrace();
                    

                    recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
                    adapter= new adapter(getApplicationContext(),videoDetailsoArrayList);
                    recyclerView.setAdapter(adapter);
                

            , new Response.ErrorListener() 
                @Override
                public void onErrorResponse(VolleyError error) 
                    Toast.makeText(getApplicationContext(),error.getMessage(), LENGTH_LONG).show();
                
            );
            requestQueue.add(stringRequest);
        

在String url中,我想为channelnames列表添加channelId,以避免添加多个活动。

PTC punjabi
UCHJW1_0oPzYZl89wX_jhrgA

Chakde Tv
UCaT-WGdJLyEDnxZPAKRTbqQ

T-series punjabi
UCJMSoNjSKRARSIJM3GymRjQ

9x tashan
UCrET5fR2NAUTO2Xp12G0l8A

zee punjabi
UCYF_LfBBxkFBEgaSCNrqW3w

上面提到的是我要分配给它们的频道ID列表,以便从MAin Activity中选择每个图像时,单独的频道活动开始。

【问题讨论】:

【参考方案1】:

如果列表中有 10 个项目,则无需为每个项目创建 10 个活动。

您只需要一个相同的活动来显示 MainActivity 列表中的详细信息。

当您按下列表中的项目时,您需要使用Intents 将它的position 和数据(在您的情况下为channel)传递给SecondActivity。

让我们进行这些更改。

在您的适配器类中:

您已经设置了侦听器,但请确保您正在传递数据。

        holder.setItemClickListener(new ItemClickListener() 
            @Override
            public void onItemClickListener(View v, int position) 
                Intent intent = new Intent(ctx, MainActivity2.class);
                // Using intent pass your data to MainActivity2 class
                intent.putExtra("Intent to MainActivity2", channel);
                ctx.startActivity(intent);
            
        );

MainActivity2 类:

现在您必须从以前的活动中接收数据。 在你的onCreate() 活动中,在扩展布局之后和设置任何视图之前。

Channel channel = getIntent().getParcelableExtra("Intent to MainActivity2");

从上面的代码中,您正在获取此意图所接收到的数据,您可能也从任何活动中接收到数据,因此具体来自您使用 getParcelableExtra() 内的 String 引用的活动

现在获取数据后,这样调用它的属性

yourTextView.setText(channel.channelname)

就是这样。现在您可以看到单击之前活动列表中的每个项目,并且不再需要额外的活动。

供您参考,您可以看到这个project 遵循类似的方法。

【讨论】:

实际上 MainActivity 3 或 4 5 是新的活动,其中包括用于通道 id 的通道解析的 json 数据。我怎样才能使用相同的活动? 所以您列表中的所有项目都没有引用或与频道数据无关?如果少数item数据不同或需要进一步操作,检查当前点击的item的位置或id,进行不同的操作。【参考方案2】:

最好在 Activity 中使用监听器参数或方法并发送位置或Class 的 Activity 点击到 MainActivity 并基于类打开 Activity 更容易,也可以在 Google 的示例中使用。

abstract class BaseAdapter : RecyclerView.Adapter<BaseAdapter.MyViewHolder>() 

    private var listener: OnRecyclerViewItemClickListener? = null

    inner class MyViewHolder
        (// each data item is just a string in this case
        private val binding: ViewDataBinding
    ) : RecyclerView.ViewHolder(binding.root), View.OnClickListener 

        internal fun bind(obj: Any) 
            binding.setVariable(BR.obj, obj)
            binding.executePendingBindings()

            // Set click listener
            itemView.setOnClickListener(this)
        

        override fun onClick(v: View) 
            listener?.run 
                onItemClicked(v, layoutPosition)
            
        

    

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder 
        // create a new view
        val layoutInflater = LayoutInflater.from(parent.context)
        val binding =
            DataBindingUtil.inflate<ViewDataBinding>(
                layoutInflater,
                getLayoutIdForType(viewType),
                parent,
                false
            )
        // set the view's size, margins, paddings and layout parameters
        return MyViewHolder(binding)
    

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) 
        holder.bind(getDataAtPosition(position))
    

   
    /**
     * Get data in position for RecyclerView row. This method is invoked inside
     * onBindViewHolder() method of RecyclerView
     *
     * @param position indicates the item for the current row
     * @return data for the current row
     */
    abstract fun getDataAtPosition(position: Int): Any
    
    /**
     * Get id of layout from R. This method is invoked from onCreateViewHolder method of Adapter
     *
     * @param viewType id of layout row of RecyclerView
     * @return id of layout
     */
    abstract fun getLayoutIdForType(viewType: Int): Int

    /**
     * RecyclerViewClickListener interface helps user to set a clickListener to the
     * RecyclerView. By setting this listener, any item of Recycler View can respond
     * to any interaction.
     */
    interface OnRecyclerViewItemClickListener 
        /**
         * This is a callback method that be overridden by the class that implements this
         * interface
         */
        fun onItemClicked(view: View, position: Int)
    

    fun setOnItemClickListener(listener: OnRecyclerViewItemClickListener) 
        this.listener = listener
    

包含类名和可选描述的数据

data class ActivityClassModel(val clazz: Class<*>, val description: String = clazz.name)

适配器实现

class ChapterSelectionAdapter(private val data: List<ActivityClassModel>) : BaseAdapter() 

    override fun getDataAtPosition(position: Int): Any 
        return data[position]
    
    override fun getLayoutIdForType(viewType: Int): Int 
        return R.layout.row_layout
    
    override fun getItemCount(): Int 
        return data.size
    

主活动

class MainActivity : AppCompatActivity(), BaseAdapter.OnRecyclerViewItemClickListener 

    private val activityClassModels = ArrayList<ActivityClassModel>()

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
   
        val activityMainBinding =
            DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)

        // Add Activities to list to be displayed on RecyclerView
        activityClassModels.add(
            ActivityClassModel(
                Activity1Basics::class.java,
                "Activity BottomNavigationView with listener"
            )
        )

        val recyclerView = activityMainBinding.recyclerView

        recyclerView.apply 

            // Use fixed size for performance
            setHasFixedSize(true)

            // use a linear layout manager
            layoutManager = LinearLayoutManager(this@MainActivity)

            // Add vertical divider
            addItemDecoration(
                DividerItemDecoration(
                    this@MainActivity,
                    DividerItemDecoration.VERTICAL
                )
            )

            // Add Adapter
            recyclerView.adapter = ChapterSelectionAdapter(activityClassModels).apply 
                setOnItemClickListener(this@MainActivity)
            
        
    

    @Override
    override fun onItemClicked(view: View, position: Int) 
        Intent(this@MainActivity, activityClassModels[position].clazz).also 
            startActivity(it)
        
    

【讨论】:

这是java代码吗?我是 Java 编程新手,我无法理解这段代码的语法。你能像我在问题中提供的代码一样用java翻译它吗

以上是关于在 RecyclerView 项目上添加多个 onClickListener的主要内容,如果未能解决你的问题,请参考以下文章

RecyclerView添加多个样式不同的Item布局

是否允许在 RecyclerView 上投放多个 AdMob 广告?另类广告网络?

RecyclerView添加动态多个HeaderView 和FooterView

RecyclerView添加动态多个HeaderView 和FooterView

Recyclerview中的多个edittext

即使在添加边距后,recyclerView 项目之间的空间也不显示