Error in OnBindViewHolder - android

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);

Related

RecyclerView not counting above 10

My RecyclerView does not count above 10 items. After the 10th item, it shows item 9 again and then item 1 and 2.
This RecyclerView produces the bug:
mViewModel.getmPremixableIngredientsLive().observe(getViewLifecycleOwner(), new Observer<ArrayList<Ingredient>>() {
#Override
public void onChanged(ArrayList<Ingredient> premixableIngredients) {
ShowIngredientsRecyclerViewAdapter premixableComponentsRecyclerViewAdpater = new ShowIngredientsRecyclerViewAdapter(premixableIngredients);
mBinding.premixableIngredientsRecyclerview.setAdapter(premixableComponentsRecyclerViewAdpater);
GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), 1);
mBinding.premixableIngredientsRecyclerview.setLayoutManager(gridLayoutManager);
}
});
This is the code of my adapter:
public class ShowIngredientsRecyclerViewAdapter extends RecyclerView.Adapter<ShowIngredientsRecyclerViewAdapter.ViewHolder> {
private ArrayList<Ingredient> mIngredients;
private IngredientRecyclerViewItemBinding mBinding;
public ShowIngredientsRecyclerViewAdapter(ArrayList<Ingredient> ingredients) {
mIngredients = ingredients;
}
#NonNull
#Override
public ShowIngredientsRecyclerViewAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
mBinding = DataBindingUtil.inflate(
LayoutInflater.from(parent.getContext()),
R.layout.ingredient_recycler_view_item,
parent,
false
);
return new ViewHolder(mBinding.getRoot());
}
#Override
public void onBindViewHolder(#NonNull ShowIngredientsRecyclerViewAdapter.ViewHolder holder, int position) {
mBinding.position.setText((position + 1) + ".");
mBinding.componentName.setText(mIngredients.get(position).getmComponent().getmName());
mBinding.amount.setText((mIngredients.get(position).getGrammPerCow() / 1000) + "kg/cow");
mBinding.dragBtn.setVisibility(View.GONE);
}
#Override
public int getItemCount() {
return mIngredients.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(#NonNull View itemView) {
super(itemView);
}
}
}
xml layout for the item:
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:id="#+id/ingredient_recyclerview_item_linearLayout"
android:background="?android:attr/selectableItemBackground"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:paddingLeft="0dp"
android:paddingStart="0dp">
<TextView
android:id="#+id/position"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1"/>
<TextView
android:id="#+id/component_name"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="Component 1"/>
<TextView
android:id="#+id/amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="50kg"/>
<ImageButton
android:id="#+id/drag_btn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:src="#drawable/ic_drag_grey"
android:background="#android:color/transparent"
android:layout_marginStart="8dp"/>
</LinearLayout>
</layout>
You are not implementing databinding correctly in your recyclerview. You shouldn't declare mBinding as a global variable in the adapter. Instead, it should be a global variable in the custom viewholder class. I share an example recyclerview adapter code with databinding below. You can adapt it to your case. Notice that binding is not a global variable in the adapter, but in the custom viewholder. And the viewholder accept binding as argument, so we pass binding instance to the viewholder when we create the viewholder and we use that instance when onBindViewHolder is called.
public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ProductViewHolder> {
private final List<Product> mProductList;
private final ProductItemClickListener mListener;
ProductAdapter(#NonNull List<Product> productList, ProductItemClickListener listener) {
mProductList =productList;
mListener = listener;
}
#NonNull
#Override
public ProductViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
ItemProductBinding binding = DataBindingUtil
.inflate(LayoutInflater.from(parent.getContext()), R.layout.item_product,
parent, false);
return new ProductViewHolder(binding);
}
#Override
public void onBindViewHolder(#NonNull ProductViewHolder holder, int position) {
holder.bind(mProductList.get(position), mListener);
}
#Override
public int getItemCount() {
return mProductList.size();
}
class ProductViewHolder extends RecyclerView.ViewHolder{
final ItemProductBinding binding;
ProductViewHolder(ItemProductBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
void bind(Product currentProduct, ProductItemClickListener clickListener){
//For each item, corresponding product object is passed to the binding
binding.setProduct(currentProduct);
binding.setProductItemClick(clickListener);
//This is to force bindings to execute right away
binding.executePendingBindings();
}
}
public interface ProductItemClickListener {
void onProductItemClicked(Product product);
}
}

Scrolling RecyclerView inside a RecyclerView Item

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" />

buttons and don't get clicked in recyclerview in adapter

I making a list of usernames and call buttons, each username has a call button next to it, when I click the call button the code inside the call button does not get executed in all clicks, I tried to make the whole item clickable so that if the user clicks on the button, the username or any part in the layout_item the code gets executed but no change happened.
Here is how I am implementing the adapter:
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View mView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.freind_list_item, parent,false);
return new MyViewHolder(mView);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
Friend friend = friends.get(position);
holder.btnInitCallHandler(friend.getUsername(), friend.get_id());
holder.setUsername(friend.getUsername());
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView txtUsername;
Button btnInitCallWithFriend;
RelativeLayout rlInsteadOfButtonHandler;
MyViewHolder(View itemView) {
super(itemView);
txtUsername = itemView.findViewById(R.id.txt_friend_item);
btnInitCallWithFriend = itemView.findViewById(R.id.btnInitCallWithFriendNormal);
friendState = itemView.findViewById(R.id.onlineState);
signedAsGlasses = itemView.findViewById(R.id.signedInAsGlasses);
signedAsLaptop = itemView.findViewById(R.id.signedInAsLaptop);
rlInsteadOfButtonHandler = itemView.findViewById(R.id.rlInsteadButtonHandler);
}
void setUsername(String username) {
txtUsername.setText(username);
}
void btnInitCallHandler(String username, String userId) {
btnInitCallWithFriend.setOnClickListener((view) -> {
Timber.tag("KingArmstringNormalUserCall").d("normal user call button clicked from the adapter");
viewAccessor.initCall(username, userId);
});
rlInsteadOfButtonHandler.setOnClickListener((v) -> {
viewAccessor.initCall(username, userId);
});
}
}
the viewAccessor is just an interface implemented by the activity, and have only one method (initCall)
the initCall(username, userId) in the Activity has only a toast and a log
EDIT:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="100dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:background="#android:color/black"
android:padding="10dp">
<TextView
android:id="#+id/txt_friend_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/txt_friend_name_placeholder"
android:textSize="30sp"
android:layout_gravity="center"
android:gravity="center"
android:textColor="#color/colorAccent"/>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<RelativeLayout
android:id="#+id/rlInsteadButtonHandler"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<!--<at.markushi.ui.CircleButton-->
<!--android:id="#+id/btnInitCallWithFriend"-->
<!--android:layout_width="70dp"-->
<!--android:layout_height="40dp"-->
<!--android:src="#drawable/ic_video_call"-->
<!--android:layout_marginStart="10dp"-->
<!--android:layout_gravity="center"-->
<!--android:focusable="false"-->
<!--android:focusableInTouchMode="false"-->
<!--app:cb_color="#fff"-->
<!--android:layout_alignParentEnd="true"/>-->
<Button
android:id="#+id/btnInitCallWithFriendNormal"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_gravity="center"
android:layout_marginStart="10dp"
android:layout_marginTop="0dp"
android:layout_marginBottom="0dp"
android:focusable="true"
android:text="call" />
</RelativeLayout>
use below code on constructor of MyViewHolder class. This code makes an item clickable.
itemView.setClickable(true);
Also set onClickLiester on MyViewHolder class. Then use getAdapterPostion() method to determine which item clicked.
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dataList.get(getAdapterPosition()); //this code will return the clicked item object.
});
First remove btnInitCallHandler() function from your ViewHolder, then set the clickListener directly in your viewHolder, you can get the current item from your list by calling getAdapterPosition() for exemple:
btnInitCallWithFriend.setOnClickListener((view) -> {
Timber.tag("KingArmstringNormalUserCall").d("normal user call button clicked from the adapter");
viewAccessor.initCall(friends.get(getAdapterPosition).getUsername(), friends.get(getAdapterPosition).get_id());
});
so this your new adapter class:
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View mView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.freind_list_item, parent,false);
return new MyViewHolder(mView);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
//do your stuff
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView txtUsername;
Button btnInitCallWithFriend;
RelativeLayout rlInsteadOfButtonHandler;
MyViewHolder(View itemView) {
super(itemView);
txtUsername = itemView.findViewById(R.id.txt_friend_item);
btnInitCallWithFriend = itemView.findViewById(R.id.btnInitCallWithFriendNormal);
friendState = itemView.findViewById(R.id.onlineState);
signedAsGlasses = itemView.findViewById(R.id.signedInAsGlasses);
signedAsLaptop = itemView.findViewById(R.id.signedInAsLaptop);
rlInsteadOfButtonHandler = itemView.findViewById(R.id.rlInsteadButtonHandler);
btnInitCallWithFriend.setOnClickListener((view) -> {
Timber.tag("KingArmstringNormalUserCall").d("normal user call button clicked from the adapter");
viewAccessor.initCall(friends.get(getAdapterPosition).getUsername(), friends.get(getAdapterPosition).get_id());
});
rlInsteadOfButtonHandler.setOnClickListener((v) -> {
viewAccessor.initCall(friends.get(getAdapterPosition).getUsername(), friends.get(getAdapterPosition).get_id());
});
}
void setUsername(String username) {
txtUsername.setText(username);
}
}
Following is a simple yet powerful implementation of RecylcerView. Try to read out the basics of recycler view and why viewholder is used. Hope this helps you out.
public class TestActivity extends Activity implements TestAdapter.ItemClickListener {
TestAdapter adapter;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_layout);
ArrayList<String> testNames = new ArrayList<>();
testNames.add("Horse");
testNames.add("Cow");
testNames.add("Camel");
testNames.add("Sheep");
testNames.add("Goat");
RecyclerView recyclerView = findViewById(R.id.testList);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new TestAdapter(this, testNames);
adapter.setClickListener(this);
recyclerView.setAdapter(adapter);
}
#Override
public void onItemClick(View view, int position) {
Toast.makeText(this, "You clicked " + adapter.getItem(position) + " on row number " + position, Toast.LENGTH_SHORT).show();
}}
Following is adapter class implementation
public class TestAdapter extends RecyclerView.Adapter<TestAdapter.MyViewHolder> {
private ItemClickListener mClickListener;
private List<String> mData;
private Activity mActivity;
public TestAdapter(TestActivity testActivity, ArrayList<String> testNames) {
this.mData = testNames;
this.mActivity = testActivity;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View mView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.test_row, parent, false);
return new MyViewHolder(mView);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
String animal = mData.get(position);
holder.txtUsername.setText(animal);
}
#Override
public int getItemCount() {
return mData.size();
}
public String getItem(int position) {
return mData.get(position);
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView txtUsername;
Button btnInitCallWithFriend;
MyViewHolder(View itemView) {
super(itemView);
txtUsername = itemView.findViewById(R.id.txt_friend_item);
btnInitCallWithFriend = itemView.findViewById(R.id.btnInitCallWithFriendNormal);
//friendState = itemView.findViewById(R.id.onlineState);
//signedAsGlasses = itemView.findViewById(R.id.signedInAsGlasses);
//signedAsLaptop = itemView.findViewById(R.id.signedInAsLaptop);
btnInitCallWithFriend.setOnClickListener((View view) -> {
Toast.makeText(mActivity, "You clicked call " + getAdapterPosition() + " position", Toast.LENGTH_SHORT).show();
});
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mClickListener != null) {
mClickListener.onItemClick(itemView, getAdapterPosition());
}
}
});
}
}
// allows clicks events to be caught
void setClickListener(ItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
// parent activity will implement this method to respond to click events
public interface ItemClickListener {
void onItemClick(View view, int position);
}}
I have finally figured out whats happening, I have been handling lots of things in the foreground, I have transferred lots of them to other threads, now it worked, u might don't believe me, but many really experienced people said to me, that they encountered a very similar situations.

Android Recycler - OnClickListener called when clicking everywhere

I have a simple adapter on a recycler view and a simple xml layout for inflation. In the xml i have 2 textviews and i register an onClickListener only to the first. But when i click to the second textview, the listener is called again. Anywhere i click the listener is called.
Any ideas? Thank you
MyRecyclerViewAdapter
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {
private List<String> mData;
private LayoutInflater mInflater;
private ItemClickListener mClickListener;
private RecyclerView rv;
// data is passed into the constructor
MyRecyclerViewAdapter(Context context, List<String> data,RecyclerView rv) {
this.mInflater = LayoutInflater.from(context);
this.mData = data;
}
// inflates the row layout from xml when needed
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.test, parent, false);
return new ViewHolder(view);
}
// binds the data to the TextView in each row
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
String animal = mData.get(position);
holder.myTextView.setText(animal);
}
// total number of rows
#Override
public int getItemCount() {
return mData.size();
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView myTextView;
ViewHolder(View itemView) {
super(itemView);
myTextView = itemView.findViewById(R.id.tvAnimalName);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("Item","clicked");
}
});
}
}
// convenience method for getting data at click position
String getItem(int id) {
return mData.get(id);
}
}`
Test Layout
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="82dp">
<TextView
android:id="#+id/tvAnimalName"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="Hello World Ankit"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="16dp"
android:layout_marginStart="24dp"
android:text="byeee"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/tvAnimalName"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
Change this :
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView myTextView;
ViewHolder(View itemView) {
super(itemView);
myTextView = itemView.findViewById(R.id.tvAnimalName);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("Item","clicked");
}
});
}
}
To:
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView myTextView;
ViewHolder(View itemView) {
super(itemView);
myTextView = itemView.findViewById(R.id.tvAnimalName);
myTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("Item","clicked");
}
});
}
}

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