I have a RecyclerView with some dummy string data in each item. Each item has also a recyclerview which contains some other dummy data (A - Z, see below) that will be visible when a button is clicked.
The problem I have is that I can not scroll the recyclerview within the item as I want. When I scroll, only the outer recyclerview scrolls (as you seen below)
Here how is it look like:
Here are the code I wrote:
//MainActivity.java
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private StringAdapter mStringAdapter;
private ArrayList<String> mStrings = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mStrings.add("This");
mStrings.add("is");
mStrings.add("a");
mStrings.add("test");
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mStringAdapter = new StringAdapter(mStrings, this);
mRecyclerView.setAdapter(mStringAdapter);
}
}
Here, the adapter resonsible for the outer main recyclerview. Note that the recyclerview of each main recyclerview item gets visible when the button is clicked :
public class StringAdapter extends RecyclerView.Adapter<StringAdapter.ViewHolder> {
private ArrayList<String> mStrings;
private Context mContext;
private SomeInnerDataAdapter mSomeInnerDataAdapter;
public StringAdapter(ArrayList<String> strings, Context context) {
mStrings = strings;
mContext = context;
}
#NonNull
#Override
public StringAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
View view = inflater.inflate(R.layout.item, viewGroup, false);
return new StringAdapter.ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull StringAdapter.ViewHolder viewHolder, int i) {
String text = mStrings.get(i);
viewHolder.onBindText(text);
}
#Override
public int getItemCount() {
return mStrings.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView mTextView;
private RecyclerView mRecyclerView;
private Button mButton;
public ViewHolder(#NonNull View itemView) {
super(itemView);
mTextView = (TextView) itemView.findViewById(R.id.textView);
mRecyclerView = (RecyclerView) itemView.findViewById(R.id.someOtherData);
mButton = (Button) itemView.findViewById(R.id.button);
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(mContext, "Item is clicked", Toast.LENGTH_LONG).show();
mRecyclerView.setVisibility(View.VISIBLE);
ArrayList<String> strings = new ArrayList<>();
strings.add("A");
strings.add("B");
strings.add("C");
strings.add("D");
strings.add("E");
strings.add("F");
strings.add("G");
strings.add("H");
strings.add("I");
strings.add("J");
strings.add("K");
strings.add("L");
strings.add("M");
strings.add("N");
strings.add("O");
strings.add("P");
strings.add("R");
strings.add("S");
strings.add("T");
strings.add("U");
strings.add("V");
strings.add("W");
strings.add("X");
strings.add("Y");
strings.add("Z");
mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false));
mSomeInnerDataAdapter = new SomeInnerDataAdapter(strings, mContext);
mRecyclerView.setAdapter(mSomeInnerDataAdapter);
}
});
}
public void onBindText(String text){
mTextView.setText(text);
}
}
}
The adapter responsible for the recyclerview within a item:
public class SomeInnerDataAdapter extends RecyclerView.Adapter<SomeInnerDataAdapter.ViewHolder> {
private ArrayList<String> mStrings;
private Context mContext;
public SomeInnerDataAdapter(ArrayList<String> strings, Context context) {
mStrings = strings;
mContext = context;
}
#NonNull
#Override
public SomeInnerDataAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
View view = inflater.inflate(R.layout.someotherdata_item, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull SomeInnerDataAdapter.ViewHolder viewHolder, int i) {
String text = mStrings.get(i);
viewHolder.onBindString(text);
}
#Override
public int getItemCount() {
return mStrings.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView mTextView;
public ViewHolder(#NonNull View itemView) {
super(itemView);
mTextView = (TextView) itemView.findViewById(R.id.someotherdata_textview);
}
public void onBindString(String text){
mTextView.setText(text);
}
}
}
The xml layouts are the following:
// item.xml
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<android.support.v7.widget.RecyclerView
android:id="#+id/someOtherData"
android:layout_gravity="right"
android:visibility="invisible"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:scrollbars="vertical" />
<Button
android:id="#+id/button"
android:text="show comment"
android:layout_gravity="bottom|center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
and someotherdata_item.xml:
<TextView
android:id="#+id/someotherdata_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android" />
Related
I'm creating an Activity Log for Lock and Unlock times, and I need my background color sorted according to Lock or Unlock. However, I cant seem to change the background color of my linear layout no matter what I put. Any help is greatly appreciated thank you!
This is my main Activity
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private RecyclerView.Adapter adapter;
private List<ListItem> listItems;
DatabaseReference database;
#Override
protected void onCreate(Bundle savedInstanceState) {
LayoutInflater inflater = LayoutInflater.from(getApplicationContext());
View view = inflater.inflate(R.layout.list_item, null);
final LinearLayout layout= (LinearLayout) view.findViewById(R.id.damsi);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
// SharedPreferences preferences=getSharedPreferences(LOCK_PREFS,MODE_PRIVATE);
database = FirebaseDatabase.getInstance().getReference("Activity Log/device321");
listItems = new ArrayList<>();
database.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot usersnapshot : dataSnapshot.getChildren()) {
Map<String, String> map = (Map<String, String>) usersnapshot.getValue();
for (Map.Entry<String, String> entry : map.entrySet()) {
if (entry.getKey().equals("LockTime")) {
System.out.println(entry.getKey());
layout.setBackgroundColor(Color.parseColor("#FFB71616"));
}
if (entry.getKey().equals("UnlockTime")) {
System.out.println(entry.getKey());
layout.setBackgroundColor(Color.parseColor("#FFB71616"));
}
listItems.add(new ListItem(entry.getKey(), entry.getValue()));
}
// ListItem listItem = usersnapshot.getValue(ListItem.class);
}
recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));
adapter = new MyAdapter(listItems, MainActivity.this);
recyclerView.setAdapter(adapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
This is My XML file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="#dimen/text_margin">
<LinearLayout
android:id="#+id/damsi"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#baa40f"
android:orientation="vertical"
android:padding="16dp"
android:visibility="visible">
<TextView
android:id="#+id/textViewHead"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffff"
android:text="Heading"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Large" />
<TextView
android:id="#+id/textViewDesc"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:text="Description" />
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
MyAdapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private List<ListItem> listItems;
private Context context;
public MyAdapter(List<ListItem> listItems, Context context) {
this.listItems = listItems;
this.context = context;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
ListItem listItem = listItems.get(position);
holder.textViewHead.setText(listItem.getHead());
holder.textViewDesc.setText(listItem.getDesc());
}
#Override
public int getItemCount() {
return listItems.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
public LinearLayout layout;
public TextView textViewHead;
public TextView textViewDesc;
public ViewHolder(View itemView) {
super(itemView);
textViewHead = (TextView) itemView.findViewById(R.id.textViewHead);
textViewDesc = (TextView) itemView.findViewById(R.id.textViewDesc);
}
}
}
Remove this code from MainActivity
LayoutInflater inflater = LayoutInflater.from(getApplicationContext());
View view = inflater.inflate(R.layout.list_item, null);
final LinearLayout layout= (LinearLayout) view.findViewById(R.id.damsi);
Remove these lines from OnDataChangedMethod
if (entry.getKey().equals("LockTime")) {
System.out.println(entry.getKey());
layout.setBackgroundColor(Color.parseColor("#FFB71616"));
}
if (entry.getKey().equals("UnlockTime")) {
System.out.println(entry.getKey());
layout.setBackgroundColor(Color.parseColor("#FFB71616"));
}
In your ViewHolder class, add these lines in your viewholder constructor.
layout= (LinearLayout) view.findViewById(R.id.damsi);
Add these lines in onBindViewHolder method.
String key = listItem.getHead();
if(key.equals("LockTime"))
{
System.out.println(entry.getKey());
layout.setBackgroundColor(Color.parseColor("#FFB71616"));
}
if(key..equals("UnlockTime")){
System.out.println(entry.getKey());
layout.setBackgroundColor(Color.parseColor("#FF001600"));
//I changed the color as both were having same hexcodes :P
}
holder.textViewHead.setText(listItem.getHead());
holder.textViewDesc.setText(listItem.getDesc());
I am creating simple screen which has one textview and button with the use of Recyclerview and Cardview.
Xml code is ready but I dont know what to write in my OnBindViewHolder class which is in my Adapter.
This is My Adapter for RecycleView
public class PaperAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<String> papers;
public TextView paperName;
public PaperAdapter(List<String> papers) {
this.papers = papers;
}
public class MyViewHolder extends RecyclerView.ViewHolder{
public MyViewHolder(View itemView) {
super(itemView);
paperName = itemView.findViewById(R.id.tvPaperName);
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View paperView = layoutInflater.inflate(R.layout.paper_row, parent, false);
MyViewHolder myViewHolder = new MyViewHolder(paperView);
return myViewHolder;
}
#Override
public void onBindViewHolder( RecyclerView.ViewHolder holder, int position) {
}
#Override
public int getItemCount() {
return papers.size();
}}
This is my MainActivity
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
List<String> papers = new ArrayList<>();
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_paper);
papers.add("Paper 1");
papers.add("Paper 2");
papers.add("Paper 3");
papers.add("Paper 4");
recyclerView = findViewById(R.id.rvPapers);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
PaperAdapter adapter = new PaperAdapter(papers);
recyclerView.setAdapter(adapter);
}
}
This is my Pagelayout xml
<?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="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="4dp"
app:cardElevation="5dp"
app:cardBackgroundColor="#A4C639"
app:cardUseCompatPadding="true"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp"
>
<TextView
android:id="#+id/tvPaperName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="paper 1"
android:textColor="#000000"
android:textSize="20sp"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="download" />
</RelativeLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
App is working without writing anything in OnBindViewHolder but its not showing Paper1,Paper2,Paper3 like this list so thats why I need to define textview in OnBindViewHolder but its showing error.Please let me know how to define textview in that and what to write in OnBindViewHolder.Also wanna set OnCLickListner for button so help me in that too.Thank you
onBindViewHolder(ViewHolder, int) is called by RecyclerView to display the data at the specified position. This method should update the contents of the RecyclerView.ViewHolder.itemView to reflect the item at the given position.
So you need to use this method to update the contents of the itemView to reflect the item at the given position.
As per your question you want to show TextView with Button in your RecyclerView, so you need to implement onBindViewHolder() as:
#Override
public void onBindViewHolder( RecyclerView.ViewHolder holder, int position) {
holder.paperName.setText(papers.get(position));
holder.download.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// TODO: Your code to download
}
});
}
You also need to give id to your button as:
<Button
android:id="#+id/btnDownload"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="download" />
And update MyViewHolder as:
public class MyViewHolder extends RecyclerView.ViewHolder{
TextView paperName;
Button download;
public MyViewHolder(View itemView) {
super(itemView);
paperName = itemView.findViewById(R.id.tvPaperName);
download = itemView.findViewById(R.id.btnDownload);
}
}
Simply, copy and paste this code in your PageAdapter class:
public class PaperAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<String> papers;
private Context mContext;
public PaperAdapter(Context context, List<String> papers) {
this.papers = papers;
this.mContext = context;
}
public class MyViewHolder extends RecyclerView.ViewHolder{
TextView paperName;
Button download;
public MyViewHolder(View itemView) {
super(itemView);
paperName = itemView.findViewById(R.id.tvPaperName);
download = itemView.findViewById(R.id.btnDownload);
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View paperView = layoutInflater.inflate(R.layout.paper_row, parent, false);
MyViewHolder myViewHolder = new MyViewHolder(paperView);
return myViewHolder;
}
#Override
public void onBindViewHolder( RecyclerView.ViewHolder holder, int position) {
holder.paperName.setText(papers.get(position));
holder.download.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(mContext, papers.get(position), Toast.LENGTH_SHORT).show();
// TODO: Your code to download
}
});
}
#Override
public int getItemCount() {
return papers.size();
}
}
EDIT: You need Context to show Toast, so pass Context in your MainActivity as:
PaperAdapter adapter = new PaperAdapter(this, papers);
I had a listview which item contain fab & textview. The listviewitem layout code bellow :
<RelativeLayout
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="wrap_content">
<android.support.design.widget.FloatingActionButton
android:id="#+id/fabActiveStat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:clickable="true"
android:focusable="false"
app:fabSize="mini"
app:srcCompat="#drawable/ic_done" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fabEdit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="0dp"
android:layout_toEndOf="#+id/fabActiveStat"
android:layout_toLeftOf="#+id/fabActiveStat"
android:clickable="true"
android:focusable="false"
app:fabSize="mini"
app:srcCompat="#android:drawable/ic_menu_edit" />
<TextView
android:id="#+id/tvDesc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/fabEdit"
android:layout_centerVertical="true"
android:layout_marginLeft="0dp"
android:layout_marginStart="0dp"
android:layout_toEndOf="#+id/fabEdit"
android:maxLines="1"
android:text=""
android:textSize="17sp"
android:clickable="true"
android:focusable="false"
android:textStyle="bold" />
</RelativeLayout>
The Adapter Code Below :
ctx = getActivity();
// The desired columns to be bound
AScolumns = new String[]{
//dbHandler.COLUMN_ID,
dbHandler.COLUMN_CATEGORY,
//dbHandler.COLUMN_ACTIVE_STATUS
};
AIto = new int[]{
//R.id.fabActiveStat,
R.id.tvDesc,
//R.id.fabEdit
};
dbHandler = new databaseHandler(ctx, null, null, 1);
csAdapter = new SimpleCursorAdapter(ctx, R.layout.view_categ_data, null, AScolumns, AIto, 0);
lvCategory.setAdapter(csAdapter);
getLoaderManager().initLoader(0, null, this);
lvCategory.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.d(TAG, "Listview di click");
}
});
}
When all fab removed and I'm using more than one textview listview on item click work just fine. But when the fab used listview on item click didn't work at all. Based on what I read on the internet focusable must be set to false, but that didn't work to. Anyone know how to put fab as list view item and make the textview & fab clickable?
Note : I am a novice
You can use RecyclerView. I use the String model here, but you can use your own custom model later. To populate a list (of items), you need to create custom adapter and custom view (just like you did). Here is the custom adapter:
public abstract class CustomAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
private List<String> data;
private LayoutInflater inflater;
public CustomAdapter(Context context, List<String> data) {
this.context = context;
this.data = data;
this.inflater = LayoutInflater.from(context);
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.custom_view, parent, false); //use your custom view here
return new BodyViewHolder(view);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
String model = data.get(position);
BodyViewHolder body = (BodyViewHolder) holder;
body.populate(model);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemCount() {
return data.size();
}
class BodyViewHolder extends RecyclerView.ViewHolder {
TextView tvDesc;
FloatingActionButton btn_edit;
FloatingActionButton btn_active;
ImageView imageView;
public BodyViewHolder(View itemView) {
super(itemView);
tvDesc = (TextView) itemView.findViewById(R.id.tvDesc);
btn_active = (FloatingActionButton) itemView.findViewById(R.id. fabActiveStat);
btn_edit = (FloatingActionButton) itemView.findViewById(R.id.fabEdit);
}
public void populate(final String model) {
tvDesc.setText(model);
btn_edit.setOnClickListener(view -> onModelClick(model));//firing listener to btn_edit, call the abstract method
}
}
public abstract void onModelClick(ProductModel model);
}
In your xml file:
<android.support.v7.widget.RecyclerView
android:padding="5dp"
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
In your activity:
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
List<String> listProduct = new ArrayList<>();
CustomAdapter adapterProduct = new CustomAdapter(getApplicationContext(), listProduct) {
#Override
public void onModelClick(String model) {
//your custom action
}
};
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setAdapter(adapterProduct);
//add some data to the ArrayList
adapter.notifyDataSetChanged();
I have to implement a custom horizontal RecyclerView having a header (title) at top and a section (See All) right side at the end of the RecyclerView.
I created a RecyclerView with a header and footer but I want to have a right sided section (See All) of which onclick event I wish to fire some event.
In Paytm App, it is implemented
I wish to get results as follows
This will Gives You Idea
activity_main.xml
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="5dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingTop="5dp">
<android.support.v7.widget.RecyclerView
android:id="#+id/verticalScrollRecyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView></RelativeLayout>
vertical_scroll_single_entry.xml
<?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="100dp"
android:weightSum="1"
android:gravity="center_vertical">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
</android.support.v7.widget.RecyclerView>
<Button
android:id="#+id/selectAllButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="See All >>"
android:textAllCaps="false"/></LinearLayout>
Custom Adapter class For Vertical Scroller
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.CustomViewHolder> {
private Context context;
private ArrayList arrayList;
private LayoutInflater layoutInflater;
public CustomAdapter(Context context, ArrayList arrayList) {
this.context = context;
this.layoutInflater = LayoutInflater.from(context);
this.arrayList = arrayList;
}
#Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = layoutInflater.inflate(R.layout.vertical_scroll_single_entry, parent, false);
return new CustomViewHolder(view);
}
#Override
public void onBindViewHolder(CustomViewHolder holder, int position) {
//initialise values to views inside holder at runtime
holder.recyclerView.setAdapter(new CustomAdapterTwo(context, arrayList));
holder.recyclerView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));
holder.recyclerView.setHasFixedSize(true);
}
#Override
public int getItemCount() {
return arrayList.size();
}
class CustomViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
RecyclerView recyclerView;
Button selectAllButton;
public CustomViewHolder(View itemView) {
super(itemView);
recyclerView = (RecyclerView) itemView.findViewById(R.id.recyclerView);
selectAllButton = (Button) itemView.findViewById(R.id.selectAllButton);
selectAllButton.setOnClickListener(this);
}
#Override
public void onClick(View v) {
Toast.makeText(context, "Select All At : " + String.valueOf(getLayoutPosition()), Toast.LENGTH_SHORT).show();
}
}}
horizontal adapter single entry file recycler_view_single_item.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="wrap_content"
android:layout_height="match_parent" android:gravity="center_horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Price"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Remove this button \n and put image view"
android:textAllCaps="false"/></LinearLayout>
Horizontal recycler view adapter class
public class CustomAdapterTwo extends RecyclerView.Adapter<CustomAdapterTwo.CustomViewHolder> {
private Context context;
private ArrayList arrayList;
private LayoutInflater layoutInflater;
public CustomAdapterTwo(Context context, ArrayList arrayList) {
this.context = context;
this.arrayList = arrayList;
this.layoutInflater = LayoutInflater.from(context);
}
#Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = layoutInflater.inflate(R.layout.recycler_view_single_item, parent, false);
return new CustomViewHolder(view);
}
#Override
public void onBindViewHolder(CustomViewHolder holder, int position) {
}
#Override
public int getItemCount() {
return arrayList.size();
}
class CustomViewHolder extends RecyclerView.ViewHolder {
public CustomViewHolder(View itemView) {
super(itemView);
}
}}
Your main activity class
public class MainActivity extends AppCompatActivity {
private RecyclerView verticalScrollRecyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initialiseView();
}
private void initialiseView() {
verticalScrollRecyclerView = (RecyclerView) findViewById(R.id.verticalScrollRecyclerView);
ArrayList<String> stringArrayList = new ArrayList<>();
stringArrayList.add("One");
stringArrayList.add("Two");
stringArrayList.add("Three");
stringArrayList.add("Four");
stringArrayList.add("Five");
stringArrayList.add("Six");
stringArrayList.add("Seven");
stringArrayList.add("Eight");
stringArrayList.add("Nine");
stringArrayList.add("Ten");
//setting adapter and layout manager to recyclerView
verticalScrollRecyclerView.setLayoutManager(new LinearLayoutManager(this));
verticalScrollRecyclerView.setAdapter(new CustomAdapter(this, stringArrayList));
verticalScrollRecyclerView.setHasFixedSize(true);
}}
Looks Like
I've got a RecyclerView which populates from an ArrayList. The output is a CardView layout.
In the Cardview, there are 2 buttons amongst other Views.
They only have to read the current value of a TextView, which by default is 1, and increase or decrease it.
The Arraylist contains 8 items.
When I run the app the UI works fine. Trouble is when I try to modify the value of the TextView.
The value is correctly increased and decreased on the CardView I'm working on, but ALSO the value is modified on another CardView. And in that second CardView, modifying its TextView value, also modifies the first one.
So, what am I doing wrong?
This is my Fragment:
public class Fragment_rosas extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.layout_rosas,container,false);
RecyclerView recyclerview_rosas;
RecyclerView.Adapter adaptador_rv_rosas;
RecyclerView.LayoutManager lm_rosas;
List rosas = new ArrayList();
rosas.add(new Tropa(1,R.drawable.minibarbaro, getResources().getString(R.string.barbaro),7,1));
recyclerview_rosas = (RecyclerView) view.findViewById(R.id.recyclerView_tropasRosas);
recyclerview_rosas.setHasFixedSize(true);
lm_rosas = new LinearLayoutManager(getContext());
recyclerview_rosas.setLayoutManager(lm_rosas);
adaptador_rv_rosas = new AdaptadorTropa(rosas);
recyclerview_rosas.setAdapter(adaptador_rv_rosas);
return view;
}
}
And here the part of code on my Adapter:
#Override
public void onBindViewHolder(final TropaViewHolder viewHolder, int i) {
viewHolder.imagen.setImageResource(items.get(i).getImagen());
viewHolder.nombre.setText(items.get(i).getNombre());
viewHolder.maxnivel.setText(String.valueOf(items.get(i).getNivelMax()));
viewHolder.espacioencamp.setText((String.valueOf(items.get(i).getEspacioEnCamp())));
final String nombre = items.get(i).getNombre();
final int maxnivel = items.get(i).getNivelMax();
viewHolder.nivelmas.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String niveltemp = viewHolder.nivel.getText().toString();
String nivelmaxtemp = viewHolder.maxnivel.getText().toString();
int nivel = Integer.parseInt(niveltemp);
int maxxnivel = Integer.parseInt(nivelmaxtemp);
int nuevonivel = nivel+1 ;
if (nuevonivel<=maxxnivel) {
viewHolder.txtv_nivel.setText(String.valueOf(nuevonivel));
}
}
});
My OnCreateViewHolder (nothing really happens here):
#Override
public TropaViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.cardview, viewGroup, false);
return new TropaViewHolder(v);
}
Here is the solution, as mentioned in the comment above, it addresses two problems:
1. positiontoValueMap - saves current value for each position
2. onclicklistener is passed to the ViewHolder in onCreateViewHolder
Adapter Class
public class MyAdapter extends RecyclerView.Adapter {
private Context context;
private List<String> dataList;
private Map<Integer, Integer> positionToValueMap = new HashMap<>();
public MyAdapter(Context context, List<String> dataList) {
this.context = context;
this.dataList = dataList;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.recycler_view_item, null, false);
return new MyViewHolder(view, new OnRecyclerItemClickListener());
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((MyViewHolder) holder).onRecyclerItemClickListener.updatePosition(position);
((MyViewHolder) holder).position.setText("" + position);
((MyViewHolder) holder).title.setText(dataList.get(position));
int valueToDisplay = 1;
if(positionToValueMap.containsKey(position)) {
valueToDisplay = positionToValueMap.get(position);
} else {
positionToValueMap.put(position, valueToDisplay);
}
((MyViewHolder) holder).valueView.setText("value: " + valueToDisplay);
}
#Override
public int getItemCount() {
return dataList.size();
}
private class MyViewHolder extends RecyclerView.ViewHolder {
private OnRecyclerItemClickListener onRecyclerItemClickListener;
private TextView position;
private TextView title;
private TextView valueView;
public MyViewHolder(View itemView, OnRecyclerItemClickListener onRecyclerItemClickListener) {
super(itemView);
itemView.setOnClickListener(onRecyclerItemClickListener);
this.onRecyclerItemClickListener = onRecyclerItemClickListener;
this.position = (TextView) itemView.findViewById(R.id.position);
this.title = (TextView) itemView.findViewById(R.id.title);
this.valueView = (TextView) itemView.findViewById(R.id.value_view);
}
}
private class OnRecyclerItemClickListener implements View.OnClickListener {
private int position = -1;
public void updatePosition(int position) {
this.position = position;
}
#Override
public void onClick(View v) {
int oldValue = positionToValueMap.get(position); // get current value
oldValue++; // increment
positionToValueMap.put(position, oldValue); // save current value
notifyItemChanged(position); // update clicked view so that it picks up the new saved value from the positionToValueMap in onBindViewHolder
}
}
}
RecyclerView item layout
<TextView
android:id="#+id/position"
android:layout_width="30dp"
android:layout_height="50dp"
android:textColor="#android:color/white"
android:gravity="center"
android:background="#android:color/holo_green_light"
android:layout_alignParentLeft="true"/>
<TextView
android:id="#+id/title"
android:layout_width="50dp"
android:layout_height="50dp"
android:textColor="#android:color/white"
android:gravity="center"
android:background="#android:color/holo_green_dark"
android:layout_toRightOf="#id/position" />
<TextView
android:id="#+id/value_view"
android:layout_width="match_parent"
android:layout_height="50dp"
android:textColor="#android:color/white"
android:gravity="center"
android:background="#android:color/holo_green_light"
android:layout_toRightOf="#id/title"
android:layout_alignParentRight="true"/>
</RelativeLayout>
And Activity to test it out
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
recyclerView.setAdapter(new MyAdapter(getApplicationContext(), getSampleData()));
}
private static List<String> getSampleData() {
List<String> dataList = new ArrayList<>();
dataList.add("zero");
dataList.add("one");
dataList.add("two");
dataList.add("three");
dataList.add("four");
dataList.add("five");
dataList.add("six");
dataList.add("seven");
dataList.add("eight");
dataList.add("nine");
dataList.add("ten");
dataList.add("eleven");
dataList.add("twelve");
dataList.add("thirteen");
dataList.add("fourteen");
dataList.add("fifteen");
dataList.add("sixteen");
dataList.add("seventeen");
dataList.add("eighteen");
dataList.add("nineteen");
dataList.add("twenty");
return dataList;
}
}
activity layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"/>
</RelativeLayout>