RecyclerView onListItemClick to create new intent - android

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)

You could implement an onClick on the view in the onBindViewHolder method of yours inside the adpater.
Assign an id to the view that holds the item cell
Get the view just the way you have for the textviews
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
}

Related

Migrating RecyclerView from Activity to Fragment - can't use findViewById

I copied the following code from the MainActivity to a separate fragment, but I can't get findViewById to work:
I get "cannot resolve method findViewById(int)"
these are the related files:
**Also as a beginner, could you let me know if there's a general problem with my code that needs to fixed?
MyFragment.java:
public class MyFragment extends Fragment {
public myFragment() {
// Required empty public constructor
}
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_my, container, false);
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
// 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);
//placeholder data
String[] myDataset = new String[16];
myDataset[0] = "Data0";
myDataset[1] = "Data1";
myDataset[2] = "Data2";
myDataset[3] = "Data3";
myDataset[4] = "Data4";
myDataset[5] = "Data5";
myDataset[6] = "Data6";
myDataset[7] = "Data7";
myDataset[8] = "Data8";
myDataset[9] = "Data9";
myDataset[10] = "Data10";
myDataset[11] = "Data11";
myDataset[12] = "Data12";
myDataset[13] = "Data13";
myDataset[14] = "Data14";
myDataset[15] = "Data15";
// specify an adapter (see also next example)
mAdapter = new MyAdapter(myDataset);
mRecyclerView.setAdapter(mAdapter);
}
}
MyAdapter.java:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private String[] 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
public static class MyViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView upTv;
public TextView downTv;
public View layout;
public MyViewHolder(View v) {
super(v);
layout = v;
upTv = (TextView)v.findViewById(R.id.upTv);
downTv = (TextView)v.findViewById(R.id.downTv);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(String[] myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.my_text_view, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.upTv.setText(mDataset[position]);
holder.downTv.setText(mDataset[position]);
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataset.length;
}
}
fragment_my.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<android.support.v7.widget.RecyclerView
android:id="#+id/my_recycler_view"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
android:scrollbars="vertical"/>
</android.support.constraint.ConstraintLayout>
my_text_view.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="6dip" >
<ImageView
android:id="#+id/icon"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
android:layout_marginRight="6dip"
android:contentDescription="TODO"
android:src="#drawable/ic_launcher_background" />
<TextView
android:id="#+id/downTv"
android:layout_width="fill_parent"
android:layout_height="26dip"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_toRightOf="#id/icon"
android:text="downTv"
android:textSize="12sp" />
<TextView
android:id="#+id/upTv"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_alignWithParentIfMissing="true"
android:layout_toRightOf="#id/icon"
android:gravity="center_vertical"
android:text="upTv"
android:textSize="16sp" />
</RelativeLayout>
Here's your problem:
return inflater.inflate(R.layout.fragment_my, container, false);
You cannot add more code after the return statement. You will need to take the reference of the inflated view and use it to find the reference of child views.
View rootView = inflater.inflate(R.layout.fragment_my, container, false);
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view);
// other code
return rootView;
A really good way to use fragments is to initialize certain variables(e.g- activity,context,root view etc) associated with the parent activity when you switch to a fragment.
for example you can do sth like,
private Context context;
private MainActivity activity; //Let MainActivity is your parent activity
private View view; //fields kept inside the fragment class,now we need to keep them initialized
//initialize activity/context from onAttach
#Override
public void onAttach(Context c) {
super.onAttach(c);
Activity a;
context=c;
if (c instanceof Activity){
a=(Activity) c;
if(a instanceof MainActivity)
activity=(MainActivity) a;
}
}
//initialize view from onViewCreated
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
this.view=view;
}
now you can use them wherever u want inside the fragment class without triggering any nullptrs and other stuff
e.g- you can go
this.view.findViewById(your_resId);
this.activity.getSupportFragmentManager();
etc and a lot of other stuffs when you need ,using these fields you initialized
also specifically in this case of using recyclerView dont forget to call,
adapter.notifyDataSetChanged() whenever you think the list you are showing in the recyclerView went through some change.
I do not have enough reputation to comment so i am writing this as answer to your comment.
You need to notify adapter using below code.
mAdapter.notifyDataSetChanged();

How can I set OnClickListener to two buttons in RecyclerView?

In my android app I have one activity to show a RecyclerView in which each row is composed by a TextView and 2 buttons. Just like that:
Well, following many explanations of internet I have made this Adapter:
public class ListAdapter extends
RecyclerView.Adapter<ListAdapter.ViewHolder> {
private LayoutInflater layoutInflater;
protected Vector<List> lists;
public ListAdapter(Context context, Vector lists) {
layoutInflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.lists = lists;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = layoutInflater.inflate(R.layout.listadapter, null);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
List list = lists.elementAt(position);
holder.name.setText(list.getName());
//holder.delete.set HOW DO I GET BUTTON HERE?
}
#Override
public int getItemCount() {
return lists.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener {
public TextView name;
public Button edit;
public Button delete;
public ViewHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.listname);
edit = (Button) itemView.findViewById(R.id.edit);
delete = (Button) itemView.findViewById(R.id.delete);
edit.setOnClickListener(this);
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.edit:
break;
case R.id.delete:
break;
default:
break;
}
}
}
}
I haven't found examples of having 2 buttons (there are only examples of adding images) in each view of the recyclerview, as in the first image. I mean, guess I have 10 List elements in my RecyclerView, how can I have in each of them to one side a TextView with the name of the List and 2 buttons and handle clickListener?. As in the following image, which I have done by hand for you to see what I am talking about:
This is the activity that will show the recyclerView; don't take it into account because I am pretty sure the way is wrong. I get lists information from sqlite database:
public class ShowListOfLists extends AppCompatActivity {
private RecyclerView recyclerView;
private RecyclerView.LayoutManager layoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_list_of_lists);
LocalDB localDB = new LocalDB(this, "localBD", null, 1);
Vector <List> ListAdapter = localDB.getAllPrivateList();
recyclerView = (RecyclerView) findViewById(R.id.recyclerviewlistas);
recyclerView.setAdapter(new ListAdapter(this, ListAdapter));
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
}
A list have the following attributes:
-idList int
-name String
-Description String
-creationDate Date
-active int (0 or 1)
-deactivationDate Date
Thank you in advance.
/*******************************EDIT****************************************/
Thank to you I have been able to show the recyclerView and it works well. But I see that:
Instead of that:
This the XML code and design of the adapter:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#drawable/rectangle_bg"
android:orientation="horizontal"
android:weightSum="1"
android:layout_marginTop="5dp">
<TextView
android:id="#+id/listname"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_weight="0.75"
android:gravity="center_vertical"
android:text="TextView"
android:textSize="15sp"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.25"
android:gravity="end"
android:orientation="vertical">
<ImageButton
android:id="#+id/delete"
android:layout_width="match_parent"
android:layout_height="30dp"
android:background="#android:color/transparent"
android:contentDescription="Delete"
app:srcCompat="#android:drawable/ic_menu_delete" />
<ImageButton
android:id="#+id/edit"
android:layout_width="match_parent"
android:layout_height="30dp"
android:background="#android:color/transparent"
android:contentDescription="Edit"
app:srcCompat="#android:drawable/ic_menu_edit" />
</LinearLayout>
</LinearLayout>
And this is the XML of the recyclerview
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="match_parent"
tools:context="com.pc.kanayel.runoutof.ShowListOfLists"
android:orientation="vertical"
android:id="#+id/recyclerviewlistas">
</android.support.v7.widget.RecyclerView>
You just need to add some code to your ListAdapter. It is there, where you have to implement onClickListener. The code for your case should look something like the one below.
You can pass any parameter you need to. It depends on the functionality you want to achieve. Here I have demonstrated passing the order of item clicked inside of list.
Option 1 (power/performance efficient)
So, what does the code below actually mean? You have already created a ViewHolder and implemented OnClickListener. That is correct. Now you need to set OnClickListener to two buttons. But what these buttons will do when clicked is defined by the interface we created inside of ViewHolder.
When app will run RecyclerView will create as many ViewHolders as it is needs to fill the available screen with list items by calling onCreateViewHolder() method for each of viewholders. When you scroll up/down these ViewHolders will be reused. OnCreateViewHolder() is not called, only onBindViewHolder() is called to update the content of viewholder. The code below made so that, when ViewHolder is created it will also create an MyClickListener that will be used by OnClickListener of viewholder and when viewholder is reused it will not create new OnClickListener. It means that our method is performance efficient.
Option 2 (not efficient)
You could also setOnClickListener() inside of onBindViewHolder(). However, as I have mentioned in the paragraph above, this method is called every time you scroll to update the content of viewholder. Now it would create new OnClickListener object everytime. While Option 1 has OnClickListener on every ViewHolder and it reuses them.
Code for Option 1
public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ViewHolder> {
private LayoutInflater layoutInflater;
protected Vector<List> lists;
public ListAdapter(Context context, Vector lists) {
layoutInflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.lists = lists;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = layoutInflater.inflate(R.layout.listadapter, null);
ViewHolder holder = new ViewHolder(view, new MyClickListener() {
#Override
public void onEdit(int p) {
// Implement your functionality for onEdit here
}
#Override
public void onDelete(int p) {
// Implement your functionality for onDelete here
}
});
return holder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
List list = lists.elementAt(position);
holder.name.setText(list.getName());
}
#Override
public int getItemCount() {
return lists.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
MyClickListener listener;
TextView name;
Button edit;
Button delete;
public ViewHolder(View itemView, MyClickListener listener) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.listname);
edit = (Button) itemView.findViewById(R.id.edit);
delete = (Button) itemView.findViewById(R.id.delete);
this.listener = listener;
edit.setOnClickListener(this);
delete.setOnClickListener(this);
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.edit:
listener.onEdit(this.getLayoutPosition());
break;
case R.id.delete:
listener.onDelete(this.getLayoutPosition());
break;
default:
break;
}
}
}
public interface MyClickListener {
void onEdit(int p);
void onDelete(int p);
}
}
Edit for your second question
To make list items take all the width set the width of your recyclerview to match_parent. It is also better to make it a child view of some layout. For instance as given below.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.pc.kanayel.runoutof.ShowListOfLists">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerviewlistas"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<RelativeLayout>
And change this code inside of your adapter:
View view = layoutInflater.inflate(R.layout.listadapter, null);
to this:
View view = layoutInflater.inflate(R.layout.listadapter, parent, false);
You can do simply like this:
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
List list = lists.elementAt(position);
holder.name.setText(list.getName());
holder.edit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Do your stuff
}
});
holder.delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Do your stuff
}
});
}

adapter for recyclerview in android

currently i am working on a android project.
where i have two String[], now i want to display the data of bothe String[] on my activity.but with my code i am only able to display the data of one String[].
plz check my code.
file name:MyAdapter4.java
public class MyAdapter4 extends RecyclerView.Adapter<MyAdapter4.MyViewHolder> {
private String[] 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
public static class MyViewHolder extends RecyclerView.ViewHolder {
public CardView cardview4;
public EditText edit4;
public TextView title4;
public MyViewHolder(View v) {
super(v);
cardview4=(CardView) v.findViewById(R.id.card_view4);
edit4=(EditText) v.findViewById(R.id.otherEdit);
title4=(TextView) v.findViewById(R.id.otherTitle);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter4(String[] myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter4.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.other_file_layout, parent, false);
// set the view's size, margins, paddings and layout parameters
MyAdapter4.MyViewHolder vh = new MyAdapter4.MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(MyAdapter4.MyViewHolder holder, int position) {
holder.title4.setText(mDataset[position]);
}
#Override
public int getItemCount() {
return mDataset.length;
}
}
with this code i am only able to display Textview.... but editText is not showing data
and this is the code which i used to attach the adapter
public class FourFragment extends Fragment {
public static String[] arrayOtherTitle, arrayOtherData;
public FourFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_four, container, false);
RecyclerView rv = (RecyclerView) rootView.findViewById(R.id.rv_recycler_view4);
rv.setHasFixedSize(true);
MyAdapter2 adapter = new MyAdapter2(arrayOtherTitle);
rv.setAdapter(adapter);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rv.setLayoutManager(llm);
return rootView;
}
}
The layout file:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_margin="4dp"
android:elevation="4dp"
android:id="#+id/card_view4"
android:layout_height="wrap_content">
<LinearLayout
android:layout_margin="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:textStyle="bold"
android:layout_weight="1"
android:id="#+id/otherTitle"
android:layout_height="wrap_content"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/copy"
android:layout_margin="4dp"/>
</LinearLayout>
<EditText
android:layout_width="match_parent"
android:id="#+id/otherEdit"
android:enabled="false"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
/>
</LinearLayout>
</android.support.v7.widget.CardView>
As you can see,
1)in my layout file, there are one textview and one edittext.
2)and in the class, FourFragment.java there are two String[] arrayOtherTitle, and arrayOtherData.
3)so, i want to display them on my activity.
where textview will contain data of arrayOtherTitle,
and editext will contain data of arrayOtherData.
but according to my code, currently i am only able to display data of arrayOtherTitle on textview.
and i am new in this topic,plz anyone help me to display the other arrayOtherData data on edittext.
please

"Recycler View..No adapter attached: skipping layout" error using Async Task in a fragment

public class ReferralStatus extends Fragment {
public MyPendingAdapter pAdapter;
public RecyclerView recyclerView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View layout= inflater.inflate(R.layout.fragment_referral_status, container, false);
recyclerView = (RecyclerView) layout.findViewById(R.id.pendingRecyclerList);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
return layout;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
PendingAsyncTask pendingRunner = new PendingAsyncTask();
pendingRunner.execute("someURL");
}
public class MyPendingAdapter extends RecyclerView.Adapter<MyPendingAdapter.PendingUserHolder> {
Context context;
String[] pendingUserArray, socialSitesArray;
public MyPendingAdapter(Context c, String[] pendingUserList, String[] socialSites) {
Log.d("golu", "pendingConstructor");
this.context=c;
this.pendingUserArray=pendingUserList;
this.socialSitesArray=socialSites;
}
public class PendingUserHolder extends RecyclerView.ViewHolder{
TextView pendingUsername;
TextView socialSite;
public PendingUserHolder(View v){
super(v);
pendingUsername = (TextView) v.findViewById(R.id.pendingUsername);
socialSite= (TextView) v.findViewById(R.id.socialSiteLabel);
}
}
#Override
public PendingUserHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Log.d("golu", "pendingHolder");
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.pending_list_row,parent,false);
PendingUserHolder holder = new PendingUserHolder(row);
return holder;
}
#Override
public void onBindViewHolder(PendingUserHolder holder, int position) {
holder.pendingUsername.setText(pendingUserArray[position]);
holder.socialSite.setText(socialSitesArray[position]);
}
#Override
public int getItemCount() {
Log.d("golu", "pendingCount");
return pendingUserArray.length;
}
}
public class PendingAsyncTask extends AsyncTask<String,Void,Boolean>{
String [] pendingUserList, socialSitesMedium;
#Override
protected Boolean doInBackground(String... params) {
//just returning simple boolean value
return true;
}
#Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
if(aBoolean)
{
//Hardcoding Arrays for now
pendingUserList=getResources().getStringArray(R.array.pendingUserList);
socialSitesMedium=getResources().getStringArray(R.array.socialSites);
pAdapter = new MyPendingAdapter(getActivity(),pendingUserList,socialSitesMedium);
recyclerView.setAdapter(pAdapter);
}
}
}
//Here is the XML file
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/pending"
android:id="#+id/pendingLabel"
android:textColor="#FF0000"
android:textAllCaps="true"
android:textStyle="bold"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:layout_marginLeft="10dp" />
<android.support.v7.widget.RecyclerView
android:id="#+id/pendingRecyclerList"
android:layout_width = "match_parent"
android:layout_height = "match_parent">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
//Its showing the Skipping layout error ....What am I doing wrong?
//FYI: I tried initialising RecyclerView and setting the LinearLayoutManager in onPostExecute....it still didnt work :/
The problem lies in OnCreateView method
You need to initialise the adapter there and set the adapter to the recycler view.
As the adapter will pass no data you can update the display later.
As the onCreateView Method is the method which updates the display,so its important to initialise it else it will give an error "no adapter attached skipping display"
What am I doing wrong?
RecyclerView (and also ListView) requires Adapter to be able to work, because adapter is the way these widgets gets the data to display from. You have adapter in your code but you lack the code that tells RecyclerView to use it: setAdapter().
See https://developer.android.com/training/material/lists-cards.html for more details

Implementing an RecycleView or CardView items with the same design for eachother

I need to know, when the user clicking on one item(or for example, whatsApp contacts) WhatsApp showing to the user one design with this picture example:
here is the recycle view items:
and i'm using :
http://code.tutsplus.com/tutorials/getting-started-with-recyclerview-and-cardview-on-android--cms-23465
Main-activity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView rv = (RecyclerView)findViewById(R.id.rv);
rv.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(context);
rv.setLayoutManager(llm);
RVAdapter adapter = new RVAdapter(persons);
rv.setAdapter(adapter);
}
}
Mainactivity Xml layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/cv"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/person_photo"
android:src="#mipmap/ic_launcher"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginRight="16dp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/person_name"
android:layout_toRightOf="#+id/person_photo"
android:layout_alignParentTop="true"
android:textSize="30sp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/person_age"
android:layout_toRightOf="#+id/person_photo"
android:layout_below="#+id/person_name"
/>
</RelativeLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/rv"/>
</LinearLayout>
here is the Adaptor:
public class RVAdapter extends RecyclerView.Adapter<RVAdapter.PersonViewHolder>{
#Override
public PersonViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.activity_main, viewGroup, false);
PersonViewHolder pvh = new PersonViewHolder(v);
return pvh;
}
#Override
public void onBindViewHolder(PersonViewHolder personViewHolder, int i) {
personViewHolder.personName.setText(persons.get(i).name);
personViewHolder.personAge.setText(persons.get(i).age);
personViewHolder.personPhoto.setImageResource(persons.get(i).photoId);
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
#Override
public int getItemCount() {
return persons.size();
}
List<Person> persons;
RVAdapter(List<Person> persons){
this.persons = persons;
}
public static class PersonViewHolder extends RecyclerView.ViewHolder {
CardView cv;
TextView personName;
TextView personAge;
ImageView personPhoto;
PersonViewHolder(View itemView) {
super(itemView);
cv = (CardView)itemView.findViewById(R.id.cv);
personName = (TextView)itemView.findViewById(R.id.person_name);
personAge = (TextView)itemView.findViewById(R.id.person_age);
personPhoto = (ImageView)itemView.findViewById(R.id.person_photo);
}
}
}
currently, there is an error in MainActivity Java codes:
cannot resolve symbol Contect and also for Person!
So, after this (i hope this fixed).
I need to when user clicked on the each item, It showing to us similar design, But, With names for each item.
Example: user clicked on item 2: Lavery Maiss
and then goto another activity or layout and show us this name.
and if user clicked on the item 1: Emma Wilson it show us in another activity same design for each item, But, with Emma Wilson name.
What should i do and what's wrong with my codes?
what we can do for showing this ?
Cheers!
After researching about this, i found a good tutorial which is no one mention it.
https://github.com/tarek360/Material-Animation-Samples
So, We need a Adaptor for doing this like below:
public class BlogRecyclerAdapter extends
RecyclerView.Adapter<BlogRecyclerAdapter.SimpleItemViewHolder> {
private List<Blog> items;
// Provide a reference to the views for each data item
// Provide access to all the views for a data item in a view holder
public final static class SimpleItemViewHolder extends RecyclerView.ViewHolder {
ImageView image;
TextView title;
TextView subTitle;
CardView cardView;
public SimpleItemViewHolder(View itemView) {
super(itemView);
image = (ImageView) itemView.findViewById(R.id.imageThumb);
title = (TextView) itemView.findViewById(R.id.title);
subTitle = (TextView) itemView.findViewById(R.id.subTitle);
cardView = (CardView) itemView.findViewById(R.id.cardView);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public BlogRecyclerAdapter(List<Blog> items) {
this.items = items;
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return this.items.size();
}
// Create new items (invoked by the layout manager)
// Usually involves inflating a layout from XML and returning the holder
#Override
public SimpleItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View itemView = LayoutInflater.from(viewGroup.getContext()).
inflate(R.layout.blog_item, viewGroup, false);
return new SimpleItemViewHolder(itemView);
}
// Replace the contents of a view (invoked by the layout manager)
// Involves populating data into the item through holder
#Override
public void onBindViewHolder(SimpleItemViewHolder viewHolder, int position) {
viewHolder.image.setImageResource(items.get(position).getImageRes());
viewHolder.image.setTag(position);
viewHolder.title.setText(items.get(position).getTitle());
viewHolder.subTitle.setText(items.get(position).getSubTitle());
viewHolder.cardView.setCardBackgroundColor(items.get(position).getBackGroundColor());
}
}
Take a look at these codes:
// Replace the contents of a view (invoked by the layout manager)
// Involves populating data into the item through holder
#Override
public void onBindViewHolder(SimpleItemViewHolder viewHolder, int position) {
viewHolder.image.setImageResource(items.get(position).getImageRes());
viewHolder.image.setTag(position);
viewHolder.title.setText(items.get(position).getTitle());
viewHolder.subTitle.setText(items.get(position).getSubTitle());
viewHolder.cardView.setCardBackgroundColor(items.get(position).getBackGroundColor());
}
Here is a good example for doing this with Animation:
https://github.com/tarek360/Material-Animation-Samples/tree/master/app/src/main/java/com/tarek360/animationsamples
exactly what we need ;)

Categories

Resources