Reputation: 4103
so, before latest update, I use onListItemClick listener and it works fine, but now I tried to use RecyclerView, and I'm not sure how to implement onClick for each item, that will open up a new activity..
this is what I used to have
public class SermonsFragment extends Fragment {
@Override
public void onListItemClick(ListView list, View v, int position, long id) {
Intent mediaStreamIntent = new Intent(getActivity(), MediaStreamPlayer.class);
mediaStreamIntent.putExtra("sermon_details", (android.os.Parcelable) list.getItemAtPosition(position));
startActivity(mediaStreamIntent);
}
}
but now, instead of using listview I create a sermon adapter and it looks like this
public class SermonListAdapter extends RecyclerView.Adapter<SermonListAdapter.ViewHolder>{
private ArrayList<Sermon> mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
//Note: need to remove static class no idea why
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
// each data item is just a string in this case
public View mView;
public ViewHolder(View v) {
super(v);
v.setOnClickListener(this);
mView = v;
}
@Override
public void onClick(View v) {
Log.d("SermonsListAdapter.java.debug", "itemClick " + mDataset.get(getPosition()).getName());
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public SermonListAdapter(ArrayList<Sermon> myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
@Override
public SermonListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.sermon_cardview, parent, false);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(v);
return vh;
}
// 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
TextView title = (TextView) holder.mView.findViewById(R.id.sermon_title);
TextView series = (TextView) holder.mView.findViewById(R.id.sermon_series);
TextView pastor = (TextView) holder.mView.findViewById(R.id.sermon_pastor);
TextView sermonDate = (TextView) holder.mView.findViewById(R.id.sermon_date);
title.setText(mDataset.get(position).getName());
series.setText(mDataset.get(position).getSeries());
pastor.setText(mDataset.get(position).getPastor());
sermonDate.setText(mDataset.get(position).getSermonDate());
}
and the fragment is more or less the same, it's just I can't use onListItemClick anymore
public class SermonsFragment extends Fragment {
private static final int MAX_SERMONS_LIST = 20;
private ArrayAdapter<Sermon> listAdapter;
private String imageUrl;
private static String sermonListJSONUrl = “http://someurl”;
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
//Check if there is internet, if yes call JSONParser
ConnectionDetector myConnection = new ConnectionDetector(getActivity().getApplicationContext());
Boolean isInternetOnline = false;
isInternetOnline = myConnection.isConnectingToInternet();
if(isInternetOnline) {
//Call JSONParser Asynchronously to get sermonList in JSON Format
new callJSONParserAsync().execute(sermonListJSONUrl);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_sermons, container, false);
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view);
return rootView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//Just an Empty Class
ArrayList<Sermon> mySermon = new ArrayList<Sermon>();
//specify an adapter
mAdapter = new SermonListAdapter(mySermon);
mRecyclerView.setAdapter(mAdapter);
}
I have the cardview xml look like this
<!-- A CardView that contains a TextView -->
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view"
android:layout_margin="5dp"
android:layout_width="match_parent"
android:layout_height="100dp"
card_view:cardCornerRadius="1dp">
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="@+id/sermon_title" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:id="@+id/sermon_series" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:id="@+id/sermon_pastor" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:id="@+id/sermon_date" />
</LinearLayout>
</android.support.v7.widget.CardView>
I've got this error when try to create new intent
12-18 22:31:48.469 31887-31887/org.ifgfseattle.ifgfseattle E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: org.ifgfseattle.ifgfseattle, PID: 31887
android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
at android.app.ContextImpl.startActivity(ContextImpl.java:1232)
at android.app.ContextImpl.startActivity(ContextImpl.java:1219)
at android.content.ContextWrapper.startActivity(ContextWrapper.java:322)
at org.ifgfseattle.ifgfseattle.adapter.SermonListAdapter$1.onClick(SermonListAdapter.java:81)
at android.view.View.performClick(View.java:4756)
at android.view.View$PerformClick.run(View.java:19749)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Upvotes: 3
Views: 21337
Reputation: 7259
You could implement an onClick
on the view in the onBindViewHolder
method of yours inside the adpater.
set an onClick to the root inside the method like this:
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
viewHolder.relLayout.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
// perform your operations here
}
});
}
EDIT:
This is how you assign an id in the xml
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/lnrLayout" ---------->> This is new
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="@+id/sermon_title" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:id="@+id/sermon_series" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:id="@+id/sermon_pastor" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:id="@+id/sermon_date" />
</LinearLayout>
This is how you define the views (or probably instantiate them)
public ViewHolder(View mView) {
super(view);
title = (TextView) holder.mView.findViewById(R.id.sermon_title);
series = (TextView) holder.mView.findViewById(R.id.sermon_series);
pastor = (TextView) holder.mView.findViewById(R.id.sermon_pastor);
sermonDate = (TextView) holder.mView.findViewById(R.id.sermon_date)
lnrLayout = (LinearLayout)holder.mView.findViewById(R.id.lnrLayout);
}
That's your custom viewholder, so declare the TextViews just the way we declare variables.. your onBindView method wil therefore look like this now:
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.title.setText(mDataset.get(position).getName());
holder.series.setText(mDataset.get(position).getSeries());
holder.pastor.setText(mDataset.get(position).getPastor());
holder.sermonDate.setText(mDataset.get(position).getSermonDate());
holder.lnrLayout.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
// on click action here
//-- use context to start the new Activity
Intent mediaStreamIntent = new Intent(mContext, MediaStreamPlayer.class);
mediaStreamIntent.putExtra("sermon_details", (android.os.Parcelable) mDataset.get(position));
mContext.startActivity(mediaStreamIntent);
}
});
}
I really have no idea why there is difference between the two, may be its because you are intializing the views inside onbind instead of the viewholder constructor.
You could also refer to this
EDIT 2: (2nd method)
Change you adapter to the following:
// Provide a suitable constructor (depends on the kind of dataset)
public SermonListAdapter(ArrayList<Sermon> myDataset, Fragment fragment) {
mDataset = myDataset;
mFragment = fragment;
}
In the onClick do this:
if(mFragment != null && mFragment instanceof SermonFragment) {
((SermonFragment)mFragment).sendToNextActivity(position); -> you can pass any data you wsh to
}
In the fragment class create a public method with the name sendToNextAcitivity with the same param definition and then call the next intent.
3rd method
Create an interface in the adapter, create a set method for the interface, implement the interface in the fragment and then initialize it, and then pass it to the set method of the adapter.
then use this:
if(mListener!= null) {
mListener.sendToNextActivity(position); -> you can pass any data you wsh to
}
Upvotes: 15