【问题标题】:how to add onClick to Fragment with recyclerView如何使用 recyclerView 将 onClick 添加到 Fragment
【发布时间】:2019-08-20 21:08:18
【问题描述】:

我有以下代码进行网络通话并显示数据列表。 该列表使用 RecyclerView 正确显示,但是我无法通过触摸一行来获得 onclick。

我已经从 onclick 中注销了该位置,并且工作正常,但应用程序因 NPE 而崩溃,因为尚未实例化 onClick 变量。

我知道我需要这样做

mAdapter.setOnClick(this);

.

但我不知道该放在哪里。

link

如何在我的片段中设置 onclick。上面的帖子使用的是 Activity 而我使用的是片段。

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.util.List;

/**
 * Created by MatthewW on 01/11/2017.
 */

public class LoneworkerGetRotaActivityFragment extends Fragment {

    private static final String TAG = LoneworkerGetRotaActivityFragment.class.getSimpleName();
    AppObj appObj;
    List<Visit> mVisitList;
    String URL;
    String companyID;
    String ID2;
    String userID;

    private RecyclerView mRecyclerView;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;






    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        appObj = (AppObj)getActivity().getApplication();
        URL = appObj.dbModel.getCompanyUrl();
        Log.e(TAG, "URL = " + URL);
        companyID = appObj.dbModel.getCompanyID();
        ID2 = appObj.dbModel.getCompanyWebServiceGuid();
        userID = appObj.dbModel.getUserID();



    }//end of onCreate






    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {


        LayoutInflater lf = getActivity().getLayoutInflater();
        View view = lf.inflate(R.layout.l_w_get_rota_activity_fragment, container, false);

        mRecyclerView = (RecyclerView) view.findViewById(R.id.get_rota_recycler_view);



        sendRequest();

        return view;


    }




    private void sendRequest(){



        StringRequest stringRequest = new StringRequest(URL + "/roadrunner.asmx/RRGetRota?ID1=" + companyID + "&ID2=" + ID2 + "&CarerID=" + userID + "&RotaDate=" + "2-Nov-2017",
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        //success - parse rota

                        DomParser dp = new DomParser(getActivity());
                        mVisitList = dp.parseUserRota(response);
                        Log.e(TAG, "mVisitList has size of " + mVisitList.size());

                        // use this setting to improve performance if you know that changes
                        // in content do not change the layout size of the RecyclerView
                        mRecyclerView.setHasFixedSize(true);

                        // use a linear layout manager
                        mLayoutManager = new LinearLayoutManager(getActivity());
                        mRecyclerView.setLayoutManager(mLayoutManager);

                        // specify an adapter (see also next example)
                        mAdapter = new MyAdapter(mVisitList);
                        mRecyclerView.setAdapter(mAdapter);








                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Toast.makeText(getActivity(), error.getMessage(), Toast.LENGTH_LONG).show();
                    }
                });


        RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
        requestQueue.add(stringRequest);
    }




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

    public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>  {


        //declare interface
        OnItemClicked onClick;



        public class ViewHolder extends RecyclerView.ViewHolder {

            public TextView tvStartDate;
            public TextView tvEndDate;
            public TextView tvDuration;
            public TextView tvClientForeName;
            public TextView tvClientSurName;


            public ViewHolder(View v) {
                super(v);
                tvStartDate = (TextView) v.findViewById(R.id.get_rota_startdate);
                tvEndDate = (TextView) v.findViewById(R.id.get_rota_enddate);
                tvDuration = (TextView) v.findViewById(R.id.get_rota_duration);
                tvClientForeName = (TextView) v.findViewById(R.id.get_rota_forename);
                tvClientSurName = (TextView) v.findViewById(R.id.get_rota_surname);
            }




        }//end of viewholder





        // Provide a suitable constructor (depends on the kind of dataset)
        public MyAdapter(List<Visit> myVisitList) {
            mVisitList = myVisitList;
        }

        // Create new views (invoked by the layout manager)
        @Override
        public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {


            View v = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.get_rota_row_layout, parent, false);

            return new ViewHolder(v);
        }

        // Replace the contents of a view (invoked by the layout manager)
        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
            // - get element from your dataset at this position
            // - replace the contents of the view with that element

            final int pos = position;

            DateTimeFormatter fmt = DateTimeFormat.forPattern("H:mm");


            String strStartDate = mVisitList.get(position).getStartDate();
            DateTime dtStartTime = new DateTime(strStartDate);
            String formattedStartTime = fmt.print(dtStartTime);
            holder.tvStartDate.setText(formattedStartTime);

            String strEndDate = mVisitList.get(position).getEndDate();
            DateTime dtEndTime = new DateTime(strEndDate);
            String formattedEndTime = fmt.print(dtEndTime);
            holder.tvEndDate.setText(formattedEndTime);

            holder.tvDuration.setText(mVisitList.get(position).getDuration());
            holder.tvClientForeName.setText(mVisitList.get(position).getClientForename());
            holder.tvClientSurName.setText(mVisitList.get(position).getClientSurname());




            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.e(TAG, "onclick pos = " + pos);
                    onClick.onItemClick(pos);

                }
            });



        }

        // Return the size of your dataset (invoked by the layout manager)
        @Override
        public int getItemCount() {
            return mVisitList.size();
        }


        public void setOnClick(OnItemClicked onClick)
        {
            this.onClick=onClick;
        }

    }//end of adapter class









}//end of class

.

 11-07 15:53:01.268 2701-2701/loneworker.carefreegroup.com.loneworker E/LoneworkerGetRotaActivityFragment: onclick pos = 1
11-07 15:53:01.269 2701-2701/loneworker.carefreegroup.com.loneworker D/AndroidRuntime: Shutting down VM


                                                                                       --------- beginning of crash
11-07 15:53:01.273 2701-2701/loneworker.carefreegroup.com.loneworker E/AndroidRuntime: FATAL EXCEPTION: main
                                                                                       Process: loneworker.carefreegroup.com.loneworker, PID: 2701
                                                                                       java.lang.NullPointerException: Attempt to invoke interface method 'void loneworker.carefreegroup.com.loneworker.LoneworkerGetRotaActivityFragment$OnItemClicked.onItemClick(int)' on a null object reference
                                                                                           at loneworker.carefreegroup.com.loneworker.LoneworkerGetRotaActivityFragment$MyAdapter$1.onClick(LoneworkerGetRotaActivityFragment.java:230)
                                                                                           at android.view.View.performClick(View.java:6213)
                                                                                           at android.view.View$PerformClick.run(View.java:23645)
                                                                                           at android.os.Handler.handleCallback(Handler.java:751)
                                                                                           at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                                           at android.os.Looper.loop(Looper.java:154)
                                                                                           at android.app.ActivityThread.main(ActivityThread.java:6692)
                                                                                           at java.lang.reflect.Method.invoke(Native Method)
                                                                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468)
                                                                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358)

【问题讨论】:

    标签: android android-recyclerview onclick


    【解决方案1】:

    在创建 MyAdater 对象后设置 OnItemClicked Lister,如下所示

    // specify an adapter (see also next example)
     mAdapter = new MyAdapter(mVisitList); // after this line
    
     mAdapter.setOnClick(new OnItemClicked() {
                @Override
                public void onItemClick(int position) {
    
                }
            });
    

    【讨论】:

    • setOnClick 方法是否存在于 MyAdapter 上?
    • 好的,那么我只需调用该方法并传递您在片段中创建的接口。
    • 嗨 Munir,是的,我在适配器中有该方法并通过了接口,但 IDE 说该方法从未使用过?就好像它不存在一样,即使在适配器类中声明了编译器也看不到它
    【解决方案2】:

    我决定以不同的方式使用 RecyclerTouchListener。

    mRecyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(),
                                    mRecyclerView, new ClickListener() {
    
                                @Override
                                public void onClick(View view, final int position) {
    
                                    Log.e(TAG, "Short press on position :" + position);
    
                                    TextView  tvDuration = (TextView) view.findViewById(R.id.get_rota_duration);
                                    String strDuration = tvDuration.getText().toString();
    
                                    try{
    
                                        Integer.parseInt(strDuration);
    
                                        //TODO create a visit from the data from webcall (in appObj) for info passed to email, text etc
    
                                        Intent i = new Intent(getActivity(), LoneworkerActivity3.class);
                                        i.putExtra("duration", strDuration);
                                        startActivity(i);
    
                                    }catch (Exception e){
                                        Toast.makeText(getActivity(), "The LoneWorker duration is not valid", Toast.LENGTH_LONG).show();
                                    }
    
    
    
    
    
                                }
    
                                @Override
                                public void onLongClick(View view, int position) {
    
                                    Log.e(TAG, "Long press on position :" + position);
                                }
    
                            }));
    

    .

    public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    
    
    
    
    
    
            public class ViewHolder extends RecyclerView.ViewHolder {
    
                public TextView tvStartDate;
                public TextView tvEndDate;
                public TextView tvDuration;
                public TextView tvClientForeName;
                public TextView tvClientSurName;
    
    
                public ViewHolder(View v) {
                    super(v);
                    tvStartDate = (TextView) v.findViewById(R.id.get_rota_startdate);
                    tvEndDate = (TextView) v.findViewById(R.id.get_rota_enddate);
                    tvDuration = (TextView) v.findViewById(R.id.get_rota_duration);
                    tvClientForeName = (TextView) v.findViewById(R.id.get_rota_forename);
                    tvClientSurName = (TextView) v.findViewById(R.id.get_rota_surname);
                }
    
    
    
    
            }//end of viewholder
    
    
    
    
    
            // Provide a suitable constructor (depends on the kind of dataset)
            public MyAdapter(List<Visit> myVisitList) {
                mVisitList = myVisitList;
            }
    
            // Create new views (invoked by the layout manager)
            @Override
            public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    
    
                View v = LayoutInflater.from(parent.getContext())
                        .inflate(R.layout.get_rota_row_layout, parent, false);
    
                return new ViewHolder(v);
            }
    
            // Replace the contents of a view (invoked by the layout manager)
            @Override
            public void onBindViewHolder(ViewHolder holder, int position) {
                // - get element from your dataset at this position
                // - replace the contents of the view with that element
    
                final int pos = position;
    
                DateTimeFormatter fmt = DateTimeFormat.forPattern("H:mm");
    
    
                String strStartDate = mVisitList.get(position).getStartDate();
                DateTime dtStartTime = new DateTime(strStartDate);
                String formattedStartTime = fmt.print(dtStartTime);
                holder.tvStartDate.setText(formattedStartTime);
    
                String strEndDate = mVisitList.get(position).getEndDate();
                DateTime dtEndTime = new DateTime(strEndDate);
                String formattedEndTime = fmt.print(dtEndTime);
                holder.tvEndDate.setText(formattedEndTime);
    
                holder.tvDuration.setText(mVisitList.get(position).getDuration());
                holder.tvClientForeName.setText(mVisitList.get(position).getClientForename());
                holder.tvClientSurName.setText(mVisitList.get(position).getClientSurname());
    
    
    
    
    
    
    
    
            }
    
            // Return the size of your dataset (invoked by the layout manager)
            @Override
            public int getItemCount() {
                return mVisitList.size();
            }
    
    
    
        }//end of adapter class
    
        public interface ClickListener{
            public void onClick(View view,int position);
            public void onLongClick(View view,int position);
        }
    
    
        class RecyclerTouchListener implements RecyclerView.OnItemTouchListener{
    
            private ClickListener clicklistener;
            private GestureDetector gestureDetector;
    
            public RecyclerTouchListener(Context context, final RecyclerView recycleView, final ClickListener clicklistener){
    
                this.clicklistener=clicklistener;
                gestureDetector=new GestureDetector(context,new GestureDetector.SimpleOnGestureListener(){
                    @Override
                    public boolean onSingleTapUp(MotionEvent e) {
                        return true;
                    }
    
                    @Override
                    public void onLongPress(MotionEvent e) {
                        View child=recycleView.findChildViewUnder(e.getX(),e.getY());
                        if(child!=null && clicklistener!=null){
                            clicklistener.onLongClick(child,recycleView.getChildAdapterPosition(child));
                        }
                    }
                });
            }
    
            @Override
            public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
                View child=rv.findChildViewUnder(e.getX(),e.getY());
                if(child!=null && clicklistener!=null && gestureDetector.onTouchEvent(e)){
                    clicklistener.onClick(child,rv.getChildAdapterPosition(child));
                }
    
                return false;
            }
    
            @Override
            public void onTouchEvent(RecyclerView rv, MotionEvent e) {
    
            }
    
            @Override
            public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
    
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-25
      • 2020-02-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多