我有以下代码来制作网络摄像头并显示数据列表。 使用RecyclerView可以正确显示列表,但是我无法通过触摸行来获得onclick。
我已经从onclick中注销了该位置并且工作正常,但应用程序因为onClick变量尚未实例化而与NPE崩溃。
我知道我需要用
做到这一点mAdapter.setOnClick(this);
但我不知道该把它放在哪里。
如何在片段中设置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(){
//https://CFTest.carefreeapp.co.uk/roadrunner.asmx/GetRotaHours?CarerID=36&RotaDate=2-Nov-2017
//https://CFTest.carefreeapp.co.uk/roadrunner.asmx/RRGetRota?ID1=900&ID2=9d817606-9194-4528-84b4-028e5aa90330&CarerID=36&RotaDate=2-Nov-2017
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)
答案 0 :(得分: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) {
}
});
答案 1 :(得分:0)
我决定使用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) {
}
}