I want to implement an onClickListener for a RecyclerViewItem in my App. My problem is, that the onclick listener isn't being called. Not even in the adapter. I'm trying to get this to work for 5 hours now and I'm really frustrated and don't know how to fix this/proceed.
I hope you can help me.
ItemListAdapter.class
public class ItemListAdapter extends RecyclerView.Adapter<ItemListAdapter.ItemViewHolder> implements Filterable {
private ArrayList<Item> mItemList;
private ArrayList<Item> mItemListFiltered;
private ItemsListAdapterListener mItemsListAdapterListener;
public ItemListAdapter(ArrayList<Item> itemArrayList, ItemsListAdapterListener itemsListAdapterListener) {
mItemList = itemArrayList;
mItemListFiltered = itemArrayList;
this.mItemsListAdapterListener = itemsListAdapterListener;
}
public interface ItemsListAdapterListener {
void onItemClick(int position);
}
public static class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public ImageView mImageView;
public TextView mTextView;
ItemsListAdapterListener mItemsListAdapterListener;
public ItemViewHolder(#NonNull View itemView, ItemsListAdapterListener itemsListAdapterListener) {
super(itemView);
mItemsListAdapterListener = itemsListAdapterListener;
mImageView = itemView.findViewById(R.id.imageViewItem);
mTextView = itemView.findViewById(R.id.textViewItem);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
mItemsListAdapterListener.onItemClick(getAdapterPosition());
Log.i("test", "Adapter click");
}
}
#NonNull
#Override
public ItemViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_view_layout, parent, false);
ItemViewHolder itemViewHolder = new ItemViewHolder(view, mItemsListAdapterListener);
return itemViewHolder;
}
#Override
public void onBindViewHolder(#NonNull ItemViewHolder holder, int position) {
Item item = mItemListFiltered.get(position);
holder.mImageView.setImageResource(item.getImgURL());
holder.mTextView.setText(item.getItemName());
}
#Override
public int getItemCount() {
return mItemListFiltered.size();
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()) {
mItemListFiltered = mItemList;
} else {
ArrayList<Item> filteredList = new ArrayList<>();
for (Item row: mItemList) {
// name match condition. this might differ depending on your requirement
// here we are looking for name or phone number match
if (row.getItemName().toLowerCase().contains(charString.toLowerCase()) || row.getItemCategory().toLowerCase().contains(charString.toLowerCase())) {
filteredList.add(row);
}
}
mItemListFiltered = (ArrayList<Item>) filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = mItemListFiltered;
return filterResults;
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
mItemListFiltered = (ArrayList<Item>) filterResults.values;
notifyDataSetChanged();
}
};
}
}
ItemsFragment.class
public class ItemsFragment extends Fragment implements TextWatcher, ItemListAdapter.ItemsListAdapterListener{
private ItemsViewModel itemsViewModel;
private RecyclerView mRecyclerView;
private ItemListAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
public View onCreateView(#NonNull final LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
itemsViewModel =
ViewModelProviders.of(this).get(ItemsViewModel.class);
View root = inflater.inflate(R.layout.fragment_items, container, false);
final EditText editTextItemSearch;
editTextItemSearch = (EditText) root.findViewById(R.id.editTextItemSearch);
editTextItemSearch.addTextChangedListener(this);
final ArrayList<Item> itemArrayList = new ArrayList<>();
itemArrayList.add(new Item("TestItem1", R.drawable.unbenannt, getString(R.string.item_parts)));
itemArrayList.add(new Item("TestItem2", R.drawable.ic_home_black_24dp, getString(R.string.item_tools)));
itemArrayList.add(new Item("TestItem3", R.drawable.ic_dashboard_black_24dp, getString(R.string.item_consumable)));
itemArrayList.add(new Item("test123", R.drawable.ic_notifications_black_24dp, getString(R.string.item_interactive)));
itemArrayList.add(new Item("test12567687863", R.drawable.ic_notifications_black_24dp,getString(R.string.item_blocks)));
Log.i("test", "items added");
mRecyclerView = root.findViewById(R.id.recylcerViewItems);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(getContext());
mAdapter = new ItemListAdapter(itemArrayList, this);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
return root;
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
mAdapter.getFilter().filter(s);
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
#Override
public void onItemClick(int position) {
Log.i("test", "item clicked");
}
}
adapter_view_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_marginBottom="6dp">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_margin="8dp"
android:backgroundTint="#color/colorBackroundBright"
android:clickable="true"
android:foreground="?attr/selectableItemBackground"
app:cardCornerRadius="15dp"
tools:layout_editor_absoluteX="144dp"
tools:layout_editor_absoluteY="42dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/imageViewItem"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_margin="16dp"
android:layout_marginStart="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/textViewItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:fontFamily="#font/nunito_regular"
android:text="ItemName"
android:textColor="#959595"
app:layout_constraintBottom_toBottomOf="#+id/imageViewItem"
app:layout_constraintStart_toEndOf="#+id/imageViewItem"
app:layout_constraintTop_toTopOf="#+id/imageViewItem" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
Try removing android:clickable="true" from your CardView.
I think what is happening is you are clicking on the CardView, which is stealing the click so the root view does not get it.
Try this:
In ItemViewHolder add a View object and set it to itemView:
public static class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public ImageView mImageView;
public TextView mTextView;
//add here
public View view;
ItemsListAdapterListener mItemsListAdapterListener;
public ItemViewHolder(#NonNull View itemView, ItemsListAdapterListener itemsListAdapterListener) {
super(itemView);
//set here
view = itemView;
.........
.........
Now set the onClickListener in onBindViewHolder:
#Override
public void onBindViewHolder(#NonNull ItemViewHolder holder, int position) {
Item item = mItemListFiltered.get(position);
holder.mImageView.setImageResource(item.getImgURL());
holder.mTextView.setText(item.getItemName());
//here
holder.view.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
mItemsListAdapterListener.onItemClick(position);
}
});
}
UPDATE:
Remove this from cardView xml:
android:clickable="true"
Related
I want to create tags using RecyclerView that can be selected to produce results.
What I want to achieve is when I tap on Books TextView on the top-right must change to Books immediately. In my case when I tap on Books it just stays in Art and it replaces Art with Books only when I replace my fragments. I also highlight buttons when clicked (changing border from grey to black) but after changing fragments highlights return back to Art again. Shortly I want to highlight button when clicked and change TextView content based on clicked button text. I partly achieved it by using interfacews but didn't get what I wanted. I provided codes below:
TrendCategoryTagsAdapter.java:
public class TrendCategoryTagsAdapter extends FirestoreRecyclerAdapter<CategorySelection, TrendCategoryTagsAdapter.TrendCategoryTagsHolder> {
Context context;
onCategoryTagClicked onCategoryTagClicked;
int row_index;
public TrendCategoryTagsAdapter(#NonNull FirestoreRecyclerOptions<CategorySelection> options, Context context, com.rajabmammadli.paragrafredesign.Interface.onCategoryTagClicked onCategoryTagClicked) {
super(options);
this.context = context;
this.onCategoryTagClicked = onCategoryTagClicked;
}
#Override
protected void onBindViewHolder(#NonNull final TrendCategoryTagsHolder holder, final int position, #NonNull CategorySelection model) {
holder.categoryNameText.setText(model.getCategoryName());
holder.categoryNameContainer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
row_index = position;
notifyDataSetChanged();
}
});
if (row_index == position) {
holder.categoryNameContainer.setBackground(ContextCompat.getDrawable(context, R.drawable.black_rounded_bg));
onCategoryTagClicked.onTagClick(holder.categoryNameText.getText().toString());
} else {
holder.categoryNameContainer.setBackground(ContextCompat.getDrawable(context, R.drawable.grey_rounded_bg));
}
}
#NonNull
#Override
public TrendCategoryTagsHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(R.layout.trendcategory_cell, parent, false);
return new TrendCategoryTagsAdapter.TrendCategoryTagsHolder(v);
}
public static class TrendCategoryTagsHolder extends RecyclerView.ViewHolder {
RelativeLayout categoryNameContainer;
TextView categoryNameText;
public TrendCategoryTagsHolder(#NonNull View itemView) {
super(itemView);
categoryNameContainer = itemView.findViewById(R.id.categoryNameContainer);
categoryNameText = itemView.findViewById(R.id.categoryNameText);
}
}
}
trendcategory_cell.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp">
<RelativeLayout
android:id="#+id/categoryNameContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/grey_rounded_bg">
<TextView
android:id="#+id/categoryNameText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/gilroyregular"
android:padding="15dp"
android:text="categoryname"
android:textColor="#android:color/black" />
</RelativeLayout>
</RelativeLayout>
TrendingFragment.java:
public class TrendingFragment extends Fragment implements onCategoryTagClicked {
RecyclerView trendingCategoryRV;
TextView noPostTV, selectedCategoryText;
FirebaseFirestore db = FirebaseFirestore.getInstance();
CollectionReference categoryRef;
String selectedCategory = "Art";
TrendCategoryTagsAdapter trendCategoryTagsAdapter;
public TrendingFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_trending, container, false);
trendPostRV = view.findViewById(R.id.trendPostRV);
trendingCategoryRV = view.findViewById(R.id.trendingCategoryRV);
noPostTV = view.findViewById(R.id.noPostTV);
selectedCategoryText = view.findViewById(R.id.selectedCategoryText);
selectedCategoryText.setText(selectedCategory);
setUpTrendCategoryTagsRV();
setUpTrendingPostRV();
// Inflate the layout for this fragment
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
trendCategoryTagsAdapter.startListening();
}
#Override
public void onDestroyView() {
super.onDestroyView();
trendCategoryTagsAdapter.stopListening();
}
private void setUpTrendCategoryTagsRV() {
categoryRef = db.collection("Categories");
Query query = categoryRef.orderBy("categoryName", Query.Direction.ASCENDING);
FirestoreRecyclerOptions<CategorySelection> options = new FirestoreRecyclerOptions.Builder<CategorySelection>()
.setQuery(query, CategorySelection.class)
.build();
trendCategoryTagsAdapter = new TrendCategoryTagsAdapter(options, getContext(), this);
trendingCategoryRV.setNestedScrollingEnabled(false);
final LinearLayoutManager trendingTagsLM = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false);
trendingCategoryRV.setLayoutManager(trendingTagsLM);
trendingCategoryRV.setAdapter(trendCategoryTagsAdapter);
trendCategoryTagsAdapter.notifyDataSetChanged();
}
#Override
public void onTagClick(String categoryName) {
selectedCategory = categoryName;
}
}
Any help will be appreciated. Thanks in advance
I have a RecyclerView and an adapter which has an ArrayList of Person model.
When the app starts I type the names in the EditText and press the button:
1)
2)
3)
4)
But when I log personList data in the activity, the result is:
personList: Item 0 -----> Alireza
personList: Item 1 -----> Tohid
personList: Item 2 -----> Alireza
First item is removed and last item is repeated in the first one. (My adapter is more complex, but I have reduced the code and views to focus on the main problem)
Adapter 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="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/tv_name"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText
android:id="#+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Name" />
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add" />
</LinearLayout>
Adapter Class:
public class TestAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private ArrayList<Person> mList;
private View.OnClickListener listener;
public TestAdapter(ArrayList<Person> mList, View.OnClickListener listener) {
this.mList = mList;
this.listener = listener;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.test_adapter_item, parent, false);
if (viewType == Person.State.FIRST.getValue()) {
return new FirstViewHolder(itemView);
} else { // if (viewType == Person.State.SECOND.getValue())
return new SecondViewHolder(itemView);
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
final int pos = holder.getAdapterPosition();
final Person person = mList.get(pos);
if (holder instanceof FirstViewHolder) {
final FirstViewHolder h = (FirstViewHolder) holder;
h.tvName.setVisibility(View.GONE);
h.etName.setVisibility(View.VISIBLE);
h.etName.setText("");
h.etName.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
person.setFirstName(s.toString());
}
#Override
public void afterTextChanged(Editable s) {
}
});
h.btnAccept.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
person.setState(Person.State.SECOND);
notifyItemChanged(pos);
listener.onClick(v);
}
});
} else { // if (holder instanceof SecondViewHolder)
final SecondViewHolder h = (SecondViewHolder) holder;
h.tvName.setVisibility(View.VISIBLE);
h.tvName.setText(person.getFirstName());
h.etName.setVisibility(View.GONE);
h.btnAccept.setVisibility(View.GONE);
}
}
private static class FirstViewHolder extends RecyclerView.ViewHolder {
private TextView tvName;
private EditText etName;
private Button btnAccept;
private FirstViewHolder(#NonNull View itemView) {
super(itemView);
tvName = itemView.findViewById(R.id.tv_name);
etName = itemView.findViewById(R.id.et_name);
btnAccept = itemView.findViewById(R.id.button);
}
}
private static class SecondViewHolder extends RecyclerView.ViewHolder {
private TextView tvName;
private EditText etName;
private Button btnAccept;
SecondViewHolder(#NonNull View itemView) {
super(itemView);
tvName = itemView.findViewById(R.id.tv_name);
etName = itemView.findViewById(R.id.et_name);
btnAccept = itemView.findViewById(R.id.button);
}
}
#Override
public int getItemCount() {
return mList.size();
}
#Override
public int getItemViewType(int position) {
return mList.get(position).getState().getValue();
}
}
Related Part of Activity:
ArrayList<Person> personList = new ArrayList<>();
personList.add(new Person("", Person.State.FIRST));
adapter = new TestAdapter(personList, new View.OnClickListener() {
#Override
public void onClick(View v) {
if (personList.size() < 3) {
personList.add(new Person("", Person.State.FIRST));
adapter.notifyItemInserted(personList.size());
} else {
for (int i = 0; i < personList.size(); i++) {
Log.i("personList", "Item " + i + " -----> " + personList.get(i).getName());
}
}
}
});
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
What's the problem? And how can I achieve correct and real ArrayList Data?
your problem lies with addTextChangedListener, when new items are added in recycler view old TextChangedListeners arent removed. and they keep changing your list items values. you should remove those listeners when state is changed to SECOND state(which is surprisingly tricky look at this How to remove all listeners added with addTextChangedListener). or you should add this validation when onTextChanged is triggered. if (person.getState() == Person.State.FIRST)
person.setFirstName(s.toString());
I'm a beginner and I'm trying to build a simple voice recorder app. I've already posted on the website concerning the access of external storage. This problem is now solved but I've an another one concerning my RecyclerView.
I've followed a tutorial online in order to detect which view is clicked and play the audio accordingly (I use my RecyclerView to display all the recording files just created). Here's the tutorial in question : https://www.youtube.com/watch?v=ZXoGG2XTjzU
The problem is, the 'OnNoteClick' does absolutely nothing. How can I fix this ?
I created an interface with a function 'OnNoteClick' attached to it. I implemented this function in mainactivity.java. Basically, I've followed the tutorial.
\\\ Adapter Code
private OnNoteListener mOnNoteListener;
...
public RecyclerViewAdapter(#NonNull ArrayList<String> text, Context context, OnNoteListener onNoteListener) {
Text = text;
this.context = context;
this.mOnNoteListener = onNoteListener;
}
...
public ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.cardview, viewGroup, false);
ViewHolder holder = new ViewHolder(view, mOnNoteListener);
return holder;
}
...
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView textView;
CardView ParentLayout;
OnNoteListener onNoteListener;
public ViewHolder(#NonNull View itemView, OnNoteListener onNoteListener) {
super(itemView);
textView = itemView.findViewById(R.id.cardtext);
ParentLayout = itemView.findViewById(R.id.cardview);
this.onNoteListener = onNoteListener;
ParentLayout.setOnClickListener(this);
}
#Override
public void onClick(View v) {
onNoteListener.onNoteClick(getAdapterPosition());
}
}
public interface OnNoteListener{
void onNoteClick(int position);
}
}
...
\\\ MainActivityCode
public class FileAndDirectoryActivity extends AppCompatActivity implements RecyclerViewAdapter.OnNoteListener {
...
private void initRecyclerView() {
RecyclerView recyclerView = findViewById(R.id.recyclerview);
RecyclerViewAdapter adapter = new RecyclerViewAdapter(mNames, this, this);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
...
#Override
public void onNoteClick(int position) {
Toast.makeText(this, "Good News : I'm working", Toast.LENGTH_SHORT).show();
}
}
...
I expect the app to show a message reading "I'm working" or something like that but in reality, when i touch the cardview, nothing happens.
Your problem is in:
public void onBindViewHolder(#NonNull ViewHolder holder, int i) {
holder.textView.setText(Text.get(i));
holder.ParentLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "onClick: Click on this card !");
}
});
}
You set a new click listener on ParentLayout so it overwrites click listener that you set in constructor. Try it without and it should work:
public void onBindViewHolder(#NonNull ViewHolder holder, int i) {
holder.textView.setText(Text.get(i));
}
Change your Adapter to below code and also Make sure you are fetching correct id of cardView
private OnNoteListener mOnNoteListener;
...
public RecyclerViewAdapter(#NonNull ArrayList<String> text, Context context, OnNoteListener onNoteListener) {
Text = text;
this.context = context;
this.mOnNoteListener = onNoteListener;
}
...
public ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(context).inflate(R.layout.cardview, viewGroup, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
...
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView textView;
CardView ParentLayout;
public ViewHolder(#NonNull View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.cardtext);
ParentLayout = itemView.findViewById(R.id.cardview);
ParentLayout.setOnClickListener(this);
}
#Override
public void onClick(View v) {
mOnNoteListener.onNoteClick(getAdapterPosition());
}
}
public interface OnNoteListener{
void onNoteClick(int position);
}
}
No need to pass listener on ViewHolder constructor, because you have mOnNoteListener as global varible.
Just create setonclicklistener of view in onBind method. And call interface method on that.
Like
mOnNoteListener.onNoteClick(pos);
pos integer as position got in onBind method
Here i given you clear explanation,
Create one common Interface, named as CustomItemClickListenere
public interface CustomItemClickListenere {
public void onItemClick(View v, int position); }
Change your adapter class like below,
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
private ArrayList<AddSingleItemList> data;
private Context mContext;
private CustomItemClickListenere listener;
public RecyclerViewAdapter(Context mContext, ArrayList<AddSingleItemList> data, CustomItemClickListenere listener) {
this.data = data;
this.mContext = mContext;
this.listener = listener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View mView = LayoutInflater.from(parent.getContext()).inflate(R.layout.items_list_single_item, parent, false);
final ViewHolder mViewHolder = new ViewHolder(mView);
mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listener.onItemClick(v, mViewHolder.getPosition());
}
});
return mViewHolder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.itemTitle.setText(Html.fromHtml(data.get(position).getTitle()));
}
#Override
public int getItemCount() {
return data.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView itemTitle;
public CardView cardView;
ViewHolder(View v) {
super(v);
itemTitle = (TextView) v.findViewById(R.id.person_name);
cardView = (CardView) v.findViewById(R.id.cv);
}
}
}
adapter's xml item_list_single_item :
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/cv"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp">
<TextView
android:id="#+id/person_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:textSize="12sp" />
</RelativeLayout>
</android.support.v7.widget.CardView>
Here i have created on Pojo class for setting static items on Recyclerview, named as AddSingleItemList :
public class AddSingleItemList {
private String title;
long id;
/**
*
* #param id
* #param title
*/
public AddSingleItemList(long id, String title) {
this.id = id;
this.title = title;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
Update you RecyclerViewActivity like below :
public class RecyclerViewActivity extends AppCompatActivity {
RecyclerView itemsList;
RecyclerViewAdapter adapter;
ArrayList<AddSingleItemList> data = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
itemsList = (RecyclerView) findViewById(R.id.items_list);
LinearLayoutManager llm = new LinearLayoutManager(this);
itemsList.setLayoutManager(llm);
itemsList.setHasFixedSize(true);
//Add you items into the Recyclerview list
data.add(new AddSingleItemList(1, "First Item"));
data.add(new AddSingleItemList(2, "Second Item"));
adapter = new RecyclerViewAdapter(this, data, new CustomItemClickListenere() {
#Override
public void onItemClick(View v, int position) {
Log.d("RecyclerViewActivity", "clicked position:" + position);
Toast.makeText(RecyclerViewActivity.this, "Good News : I'm working", Toast.LENGTH_SHORT).show();
// do what ever you want to do with it
}
});
itemsList.setAdapter(adapter);
}
}
Finally you will get result as you raised in your question,
I want to show another activity when object of recycler view is clicked. For eg: if I clicked "dd" text or"image of that line" then I should go to activity named "AbcActivity".
It went to many site, saw youtube tutorial but didn't helped. please help me with it. Please help me out this is my last hope :(
I'm beginner in this, It'd be great if you can provide project.
This is main activity:
public class MainActivity extends AppCompatActivity implements WordAdapter.OnNoteListener {
private RecyclerView recyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.home_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
List<Word> wordList = new ArrayList<>();
wordList.add(new Word(R.drawable.ic_launcher_background, "dd"));
wordList.add(new Word(R.drawable.ic_launcher_background, "ss"));
WordAdapter adapter = new WordAdapter(wordList, this);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
#Override
public void onNoteClick(int position) {
}
}
WordAdapter:
public class WordAdapter extends RecyclerView.Adapter<WordAdapter.viewholder> {
private List<Word> wordList;
private OnNoteListener mOnNoteListener;
public WordAdapter(List<Word> wordList, OnNoteListener onNoteListener) {
this.wordList = wordList;
this.mOnNoteListener = onNoteListener;
}
#NonNull
#Override
public viewholder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_items, viewGroup, false);
return new viewholder(view, mOnNoteListener);
}
#Override
public void onBindViewHolder(#NonNull viewholder viewholder, int position) {
int resource = wordList.get(position).getImageResource();
String title = wordList.get(position).getTitle();
viewholder.setData(resource, title);
}
#Override
public int getItemCount() {
return wordList.size();
}
class viewholder extends RecyclerView.ViewHolder implements View.OnClickListener{
private ImageView imageView;
private TextView title;
OnNoteListener onNoteListener;
public viewholder(#NonNull View itemView, OnNoteListener onNoteListener) {
super(itemView);
imageView = itemView.findViewById(R.id.image);
title = itemView.findViewById(R.id.word);
this.onNoteListener = onNoteListener;
itemView.setOnClickListener(this);
}
private void setData(int resource, String titleText){
imageView.setImageResource(resource);
title.setText(titleText);
}
#Override
public void onClick(View view) {
onNoteListener.onNoteClick(getAdapterPosition());
}
}
public interface OnNoteListener {
void onNoteClick(int position);
}
}
This is word:
public class Word implements Parcelable {
private int imageResource;
private String title;
public Word(int imageResource, String title) {
this.imageResource = imageResource;
this.title = title;
}
protected Word(Parcel in) {
imageResource = in.readInt();
title = in.readString();
}
public static final Creator<Word> CREATOR = new Creator<Word>() {
#Override
public Word createFromParcel(Parcel in) {
return new Word(in);
}
#Override
public Word[] newArray(int size) {
return new Word[size];
}
};
public int getImageResource() {
return imageResource;
}
public String getTitle() {
return title;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(imageResource);
parcel.writeString(title);
}
}
Your code works to a big percent fine. Not sure what is the problem. Maybe you have a problem when starting the new activity but surely this code has no issues.
I will post below your example with small modifications to the ViewHolder.
public class MainActivity extends AppCompatActivity implements WordAdapter.OnNoteListener {
private RecyclerView recyclerView;
private static final String TAG = MainActivity.class.getCanonicalName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.home_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
List<Word> wordList = new ArrayList<>();
wordList.add(new Word(R.drawable.ic_launcher_background, "dd"));
wordList.add(new Word(R.drawable.ic_launcher_background, "ss"));
wordList.add(new Word(R.drawable.ic_launcher_background, "cc"));
WordAdapter adapter = new WordAdapter(this);
recyclerView.setAdapter(adapter);
adapter.addItems(wordList);
}
#Override
public void onNoteClick(int position) {
Log.d(TAG, "clicked on the position:" + position);
}
}
public class WordAdapter extends RecyclerView.Adapter<WordAdapter.ViewHolder> {
private List<Word> wordList;
private OnNoteListener mOnNoteListener;
public WordAdapter(List<Word> wordList, OnNoteListener onNoteListener) {
this.wordList = wordList;
this.mOnNoteListener = onNoteListener;
}
public WordAdapter(OnNoteListener onNoteListener) {
this(new ArrayList<Word>(), onNoteListener);
}
public void addItems(List<Word> items) {
wordList.addAll(items);
notifyDataSetChanged();
}
public void clear() {
wordList.clear();
notifyDataSetChanged();
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_items, viewGroup, false);
return new ViewHolder(view, mOnNoteListener);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder viewholder, int position) {
int resource = wordList.get(position).getImageResource();
String title = wordList.get(position).getTitle();
viewholder.setData(resource, title);
}
#Override
public int getItemCount() {
return wordList.size();
}
static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private ImageView imageView;
private TextView title;
private OnNoteListener onNoteListener;
public ViewHolder(#NonNull View itemView, OnNoteListener onNoteListener) {
super(itemView);
imageView = itemView.findViewById(R.id.imageView);
title = itemView.findViewById(R.id.word);
this.onNoteListener = onNoteListener;
itemView.setOnClickListener(this);
}
private void setData(int resource, String titleText) {
imageView.setImageResource(resource);
title.setText(titleText);
}
#Override
public void onClick(View view) {
onNoteListener.onNoteClick(getAdapterPosition());
}
}
public interface OnNoteListener {
void onNoteClick(int position);
}
}
The word class stays the same.
Now, regarding the xml, I put some quick stuff below(list_item.xml):
<android.support.constraint.ConstraintLayout 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:background="#color/md_green_100"
android:orientation="horizontal"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp">
<TextView
android:id="#+id/word"
android:layout_width="86dp"
android:layout_height="36dp"
android:layout_marginStart="8dp"
android:gravity="center"
android:text="Word 1"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/imageView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/imageView"
android:layout_width="120dp"
android:layout_height="160dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:background="#drawable/ic_launcher_background"
android:contentDescription="Icon"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/word"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
Below you can find a screenshot of the click events.
Now, knowing that click events work do whatever you want, startActivity, Log, etc.
You can set an OnClickListener for your viewHolder's itemView.
This will start the AbcActivity when you click on the imageView of the viewholder.
#Override
public void onBindViewHolder(#NonNull viewholder viewholder, int position) {
int resource = wordList.get(position).getImageResource();
String title = wordList.get(position).getTitle();
viewholder.setData(resource, title);
// #ADDED
// viewholder.itemView or viewholder.title will work too
viewholder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
void onClick(View v) {
// start activity
Context context = viewHolder.itemView.getContext();
Intent intent = new Intent(context, AbcActivity.class);
context.startActivity(intent);
}
});
}
You've done almost everything.
All that remains is actually handling the click event that the listener you passed to your adapter is letting you know in the activity.
Change
#Override
public void onNoteClick(int position) {
}
To this
#Override
public void onNoteClick(int position) {
Intent intent = new Intent(context, AbcActivity.class);
context.startActivity(intent);
}
in your activity
I have a horizontal RecyclerView that shows images for selection of a "profile" image.
I'm using CircleImageView to leave the images with rounded corners, this library makes it possible to place a border on each image.
Note a RecyclerViewItemLayout.xml
<?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:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/avatar_select"
android:paddingTop="5dp"
android:layout_width="80dp"
android:layout_height="80dp"
android:padding="5dp"
app:civ_border_color="#color/colorPrimary"
app:civ_border_width="3dp"
android:src="#drawable/avatar1"/>
</LinearLayout>
When an item is clicked, the CircleImageView border should match the color of the ColorAsset, and when a new item is clicked (as if the user changed his or her opinion about the "profile" photo and wanted another), the new item should receive the border and the old selection should return to ColorPrimary.
Note a RecyclerViewAdapter.java
public class AvatarAdapter extends RecyclerView.Adapter<AvatarAdapter.MyViewHolder> {
private Context mContext;
private List<Avatar> mdata;
public AvatarAdapter(Context mContext, List<Avatar> mdata) {
this.mContext = mContext;
this.mdata = mdata;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view;
LayoutInflater mInflater = LayoutInflater.from(mContext);
view = mInflater.inflate(R.layout.escolhe_avatar,parent,false);
final MyViewHolder vHolder = new MyViewHolder(view);
return vHolder;
}
#Override
public void onBindViewHolder(#NonNull final MyViewHolder holder, int position) {
holder.image.setImageResource(mdata.get(position).getImage());
holder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.image.setBorderColor(R.color.colorAccent);
}
});
}
});
}
#Override
public int getItemCount() {
return mdata.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
private CircleImageView image;
public MyViewHolder(View itemView){
super(itemView);
image = (CircleImageView) itemView.findViewById(R.id.avatar_select);
}
}
}
I already broke my head, I researched but I could not reach a solution, can anyone help me please?
Taking advantage of a logic from a previous answer, I thought that with each click, I should update all the items execto the one that receive the edge of ColorAccent.
Veja a minha classe onBindViewClass do meu RecyclerViewAdapter.class
#Override
public void onBindViewHolder(#NonNull final MyViewHolder holder, final int position) {
holder.image.setImageResource(mdata.get(position).getImage());
holder.image.setBorderColor(getColor(mContext, R.color.colorPrimary));
holder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.image.setBorderColor(getColor(mContext, R.color.colorAccent));
for (int i=0; i <= mdata.size(); i++){
if (i != position){
notifyItemChanged(i, null);
}
}
}
});
}
if i understood correctly what you want to do this should work
#Override
public void onBindViewHolder(#NonNull final MyViewHolder holder, int position) {
holder.image.setImageResource(mdata.get(position).getImage());
holder.image.setBorderColor(R.color.colorPrimary);
holder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
notifyDataSetChanged();
holder.image.setBorderColor(R.color.colorAccent);
}
});
}
});
}