How to fix this issue in Recycler view? - android

I have a recycler view when clicked on the item VISIBLE hide seek bar for each item.
the issue is when clicked on a single item then VISIBLE multiple hides seek bar and also when scrolling up down auto show randomly seek bar in this recycler view. help me. Thanks
See in this screenshot
Adapter class
public class Adapter_Custom extends RecyclerView.Adapter<Adapter_Custom.ViewHolder> {
private Adapter_Custom.OnItemClickListener mListener;
public interface OnItemClickListener {
void onImageClick(int position,ImageView imageView,SeekBar seekBar);
void onSeekBarProgressChange(int position,String progress);
}
public void setOnItemClickListener(Adapter_Custom.OnItemClickListener listener) {
mListener = listener;
}
Context MyContext;
List<Model_main> modelList;
public Adapter_Custom(Context myContext, List<Model_main> modelList) {
MyContext = myContext;
this.modelList = modelList;
}
#NonNull
#Override
public Adapter_Custom.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(MyContext);
View view = inflater.inflate(R.layout.rv_item_custom, null, false);
return new Adapter_Custom.ViewHolder(view, mListener);
}
#Override
public void onBindViewHolder(#NonNull final Adapter_Custom.ViewHolder holder, int position) {
final Model_main model = modelList.get(position);
holder.textView3.setText(model.getName());
holder.sound_image.setImageResource(model.getImages());
}
#Override
public int getItemCount() {
return modelList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView textView3;
ImageView sound_image;
SeekBar seekBar;
public ViewHolder(#NonNull final View itemView, final Adapter_Custom.OnItemClickListener listener) {
super(itemView);
textView3 = itemView.findViewById(R.id.textView3);
sound_image = itemView.findViewById(R.id.sound_image);
seekBar = itemView.findViewById(R.id.seekBar);
sound_image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
listener.onImageClick(position,sound_image,seekBar);
// Toast.makeText(MyContext, ""+position, Toast.LENGTH_SHORT).show();
}
}
}
});
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
if (listener != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
listener.onSeekBarProgressChange(position,String.valueOf(seekBar.getProgress()));
}
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
}
}
ClickListner
adapter_custom1.setOnItemClickListener(new Adapter_Custom.OnItemClickListener() {
#Override
public void onImageClick(int position, ImageView imageView, SeekBar seekBar) {
Toast.makeText(getContext(), "" + position, Toast.LENGTH_SHORT).show();
rv.findViewHolderForAdapterPosition(position).itemView.findViewById(R.id.seekBar)
.setVisibility(isVisible()? View.VISIBLE : View.GONE);
// rv.findViewHolderForAdapterPosition(position).itemView.findViewById(R.id.seekBar).setVisibility(View.VISIBLE);
// rv.findViewHolderForAdapterPosition(position).itemView.findViewById(R.id.textView3).setVisibility(View.GONE);
if (custom_btn_div.getVisibility() == View.GONE) {
custom_btn_div.setVisibility(View.VISIBLE);
}
}

Problem: Setting view visibility or checkbox check or drawable an ImageView to one or some of a RecyclerView items (rows).
Solution: You need to negate the opposite to remaining Views; e.g. If you set visiblity of a row item view to VISIBLE, then you've to make sure to set it as GONE/INVISIBLE to the similar items of the other rows.
Reason: Because the RecyclerView, as indicates from its name, recycles views; so if it needs to hold 100 items; and the screen size can hold 10 items at a time; then with the next scroll of the RecyclerView it doesn't create those items from the scrach, but copies the data of the new items into their place holds; if the data (visibility) is not set, then it takes the old data.
#Override
public void onBindViewHolder(#NonNull final Adapter_Custom.ViewHolder holder, int position) {
final Model_main model = modelList.get(position);
holder.textView3.setText(model.getName());
holder.sound_image.setImageResource(model.getImages());
holder.seekBar.setVisibility(View.GONE);
}

Related

Why do values ​disappear after scrolling in Recycler View?

Data before scrolling
Data after scrolling
The problem with my app is shown in the pictures above.
After entering the data, if i scroll after adding the item as scrollable, the data disappears.
As a further explanation, sometimes the entered data appears in other items that have been added.
To explain the app, it is an exercise recording app, and it uses a multi-type recycler view.
I used ListAdapter and also DiffUtil. And the picture is related to the Detail item.
TextWatcher was used to save the entered data.
I've been searching a lot to solve this.
The two most searched solutions are here
using getItemViewType(), getItemId()
->I used this method as shown in this link, but it didn't solve the problem.
Using setIsRecyclable(false) inside the holder
-> This method worked. But I heard that setIsRecyclable(false) is a function that does not recycle.
If i use this, isn't it a good way to do it because there is no advantage to using RecyclerView?
RoutineAdapter.java
public class RoutineListAdapter extends ListAdapter<Object, RecyclerView.ViewHolder> {
Context context;
RoutineListAdapter.OnRoutineItemClickListener routinelistener;
RoutineListAdapter.OnRoutineAddClickListener routineAddListener;
final static int TYPE_ROUTINE = 1;
final static int TYPE_ROUTINE_DETAIL = 2;
final static int TYPE_ROUTINE_FOOTER = 3;
public RoutineListAdapter(#NonNull DiffUtil.ItemCallback<Object> diffCallback) {
super(diffCallback);
}
// add routine interface
public interface OnRoutineAddClickListener {
public void onAddRoutineClick();
}
public void setOnAddRoutineClickListener(RoutineListAdapter.OnRoutineAddClickListener listener) {
this.routineAddListener = listener;
}
// add/remove detail interface
public interface OnRoutineItemClickListener {
public void onAddBtnClicked(int curRoutinePos);
public void onDeleteBtnClicked(int curRoutinePos);
public void onWritingCommentBtnClicked(int curRoutinePos);
}
public void setOnRoutineClickListener(RoutineListAdapter.OnRoutineItemClickListener listener) {
this.routinelistener = listener;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
context = parent.getContext();
View itemView;
if(viewType == TYPE_ROUTINE){
itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.routine_item, parent, false);
return new RoutineListAdapter.RoutineViewHolder(itemView);
}
else if(viewType == TYPE_ROUTINE_DETAIL){
itemView = LayoutInflater.from(context).inflate(R.layout.routine_detail_item, parent, false);
return new RoutineListAdapter.RoutineDetailViewHolder(itemView);
}
else {
itemView = LayoutInflater.from(context).inflate(R.layout.add_routine_item, parent, false);
return new RoutineListAdapter.RoutineAddFooterViewHolder(itemView);
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
Object curItem;
switch (getItemViewType(position)) {
case TYPE_ROUTINE:
curItem = getItem(position);
setRoutineData((RoutineListAdapter.RoutineViewHolder) holder, (RoutineModel) curItem);
break;
case TYPE_ROUTINE_DETAIL:
curItem = getItem(position);
RoutineDetailModel item = (RoutineDetailModel) curItem;
((RoutineListAdapter.RoutineDetailViewHolder) holder).bind(item);
((RoutineDetailViewHolder) holder).weight.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) {
}
#Override
public void afterTextChanged(Editable s) {
item.setWeight(((RoutineDetailViewHolder) holder).weight.getText().toString());
}
});
break;
case TYPE_ROUTINE_FOOTER:
break;
}
}
private void setRoutineData(RoutineListAdapter.RoutineViewHolder holder, RoutineModel routineItem){
holder.routine.setText(routineItem.getRoutine());
}
public Object getRoutineItem(int position) {
if(getCurrentList() == null || position < 0 || position >= getCurrentList().size())
return null;
return getItem(position);
}
#Override
public int getItemCount() {
return getCurrentList().size() + 1;
}
#Override
public int getItemViewType(int position) {
if(position == getCurrentList().size()) {
return TYPE_ROUTINE_FOOTER;
}
else {
Object obj = getItem(position);
if(obj instanceof RoutineModel) {
return TYPE_ROUTINE;
}
else {
// obj instanceof RoutineDetailModel
return TYPE_ROUTINE_DETAIL;
}
}
}
private class RoutineViewHolder extends RecyclerView.ViewHolder {
public TextView routine;
public Button addSet;
public Button deleteSet;
public Button comment;
public RoutineViewHolder(#NonNull View itemView) {
super(itemView);
routine = itemView.findViewById(R.id.routine);
addSet = itemView.findViewById(R.id.add_set);
deleteSet = itemView.findViewById(R.id.delete_set);
comment = itemView.findViewById(R.id.write_comment);
addSet.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(routinelistener != null && getAdapterPosition() != RecyclerView.NO_POSITION)
routinelistener.onAddBtnClicked(getAdapterPosition());
}
});
deleteSet.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(routinelistener != null && getAdapterPosition() != RecyclerView.NO_POSITION)
routinelistener.onDeleteBtnClicked(getAdapterPosition());
}
});
comment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(routinelistener != null && getAdapterPosition() != RecyclerView.NO_POSITION)
routinelistener.onWritingCommentBtnClicked(getAdapterPosition());
}
});
}
}
private class RoutineDetailViewHolder extends RecyclerView.ViewHolder {
private TextView set;
private EditText weight;
public RoutineDetailViewHolder(#NonNull View itemView) {
super(itemView);
set = itemView.findViewById(R.id.set);
weight = itemView.findViewById(R.id.weight);
}
private void bind(RoutineDetailModel item) {
set.setText(item.getSet().toString() + "set");
weight.setText(item.getWeight());
}
}
private class RoutineAddFooterViewHolder extends RecyclerView.ViewHolder {
TextView textView;
public RoutineAddFooterViewHolder(#NonNull View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.add_text);
ConstraintLayout regionForClick = itemView.findViewById(R.id.clickable_layout);
regionForClick.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (routineAddListener != null) {
routineAddListener.onAddRoutineClick();
}
}
});
}
}
}
UPDATED
Adapter
public class RoutineListAdapter extends ListAdapter<Object, RecyclerView.ViewHolder> {
// detail add / remove iterface
public interface OnRoutineItemClickListener {
public void onAddBtnClicked(int curRoutinePos);
public void onDeleteBtnClicked(int curRoutinePos);
public void onWritingCommentBtnClicked(int curRoutinePos);
public void onWritingWeight(int curRoutinePos, View view); // write weight
}
public void setOnRoutineClickListener(RoutineListAdapter.OnRoutineItemClickListener listener) {
if(this.routinelistener != null)
this.routinelistener = null;
this.routinelistener = listener;
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
Object curItem;
switch (getItemViewType(position)) {
case TYPE_ROUTINE:
curItem = getItem(position);
setRoutineData((RoutineListAdapter.RoutineViewHolder) holder, (RoutineModel) curItem);
break;
case TYPE_ROUTINE_DETAIL:
((RoutineListAdapter.RoutineDetailViewHolder) holder).bind();
break;
case TYPE_ROUTINE_FOOTER:
break;
}
}
private class RoutineDetailViewHolder extends RecyclerView.ViewHolder {
private TextView set;
private EditText weight;
public RoutineDetailViewHolder(#NonNull View itemView) {
super(itemView);
set = itemView.findViewById(R.id.set);
weight = itemView.findViewById(R.id.weight);
weight.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) {
}
#Override
public void afterTextChanged(Editable s) {
routinelistener.onWritingWeight(getAdapterPosition(), itemView);
}
});
}
private void bind() {
RoutineDetailModel item = (RoutineDetailModel) getItem(getAdapterPosition());
set.setText(item.getSet().toString() + "set");
weight.setText(item.getWeight()); // Setting the saved value
}
}
Activity
public class WriteRoutineActivity extends AppCompatActivity implements WritingCommentDialogFragment.OnDialogClosedListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_write_routine);
initViews();
setPageTitle(getIntent());
setRoutineRecyclerview();
diffUtil2 = new RoutineDiffUtil2();
listAdapter = new RoutineListAdapter(diffUtil2);
items = new ArrayList<>();
routine_rv.setAdapter(listAdapter);
listAdapter.setOnRoutineClickListener(new RoutineListAdapter.OnRoutineItemClickListener() {
#Override
public void onWritingWeight(int curRoutinePos, View v) {
RoutineDetailModel item = (RoutineDetailModel) listAdapter.getRoutineItem(curRoutinePos);
EditText weight = v.findViewById(R.id.weight);
item.setWeight(weight.getText().toString()); // This is saved to set the value again when recycled.
});
}
}
If you need any other extra code, please tell me
The issue lies with your TextWatcher that you're adding in onBindViewHolder.
At the moment you have it setup so that every time the RecyclerView binds a view (which can happen multiple times per actual view), you're adding a new TextWatcher and then also setting the text to the item's weight, which is then triggering the previous watchers you added, setting the item's weight to something else, in this case an empty string.
What you should be doing is either removing all listeners before you add another one, or add the listener in onCreateViewHolder and use the holder's adapter position to get your item.
Here is some pseudocode to clarify my suggestions:
Adding the listener in onCreateViewHolder
RoutineDetailViewHolder {
private EditText weight;
RoutineDetailViewHolder {
weight.addTextChangedListener {
items[adapterPosition].setWeight(...)
}
}
}
Removing the listeners before binding again:
RoutineDetailViewHolder {
private EditText weight;
private TextWatcher weightWatcher;
void bind() {
weight.removeTextChangedListener(weightWatcher);
weightWatcher = new TextWatcher();
weight.addOnTextChangedListener(weightWatcher);
}
}

Change image view background of View Pager2 selected image in android

I am trying to changing the background imageview of viewpager2 selected imageview in android. But in my case not changing image view background, when viewpager2 selected. Below code to change image view background.
final List<Integer> names = new ArrayList<Integer>();
for(int i=0;i<5;i++){
names.add(i);
}
insideRoomAdapter = new InsideRoomAdapter(context,names);
viewPager.setAdapter(insideRoomAdapter);
viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
}
#Override
public void onPageSelected(int position) {
super.onPageSelected(position);
for(int i=0;i<names.size();i++){
if(names.get(position) == position){
Toast.makeText(context,"pos:"+ names.get(position),Toast.LENGTH_SHORT).show();
insideRoomAdapter.imageView.setBackground(ContextCompat.getDrawable(context,R.drawable.selected_light_bg));
viewPager.getAdapter().notifyDataSetChanged();
}else {
insideRoomAdapter.imageView.setBackground(ContextCompat.getDrawable(context,R.drawable.inside_room_item_bg));
viewPager.getAdapter().notifyDataSetChanged();
}
}
}
#Override
public void onPageScrollStateChanged(int state) {
super.onPageScrollStateChanged(state);
}
});
My Adapter class
public class InsideRoomAdapter extends RecyclerView.Adapter<InsideRoomAdapter.ViewHolder> {
Context context;
List<Integer> list;
ImageView imageView;
public InsideRoomAdapter(Context context,List<Integer> list) {
this.context = context;
this.list = list;
}
#NonNull
#Override
public InsideRoomAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.inside_room_items,parent,false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull InsideRoomAdapter.ViewHolder holder, int position) {
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context,"light clicked",Toast.LENGTH_LONG).show();
}
});
}
#Override
public int getItemCount() {
return list.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(#NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.inside_light_img);
}
}
}
Anyone can guide me how to change image view background, when viewpager2 selected.
Expected like this
Thanks in Advance.
I think you are approaching this in the wrong way. What you need is a public method for your adapter which stores the position selected from your viewpager2's onPageSelected() and in onBindViewHolder() method of your adapter simply use a check for selecting the background to use.
I have made changes to your adapter as below:
public class InsideRoomAdapter extends RecyclerView.Adapter<InsideRoomAdapter.ViewHolder> {
private Context context;
private List<Integer> list;
//moved ImageView to ViewHolder class as private
private int selectedPosition; //the int value for keeping track of your selected position
public InsideRoomAdapter(Context context,List<Integer> list) {
this.context = context;
this.list = list;
this.selectedPosition = 0; //initialize it here
}
#NonNull
#Override
public InsideRoomAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.inside_room_items,parent,false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull InsideRoomAdapter.ViewHolder holder, int position) {
/* Since ImageView was moved reference it from the holder like below
* Use a simple check to verify it the adapter position matches with the selectedPosition
* if so simply set the backgrounds as required
*/
if(position == selectedPosition) {
holder.imageView.setBackground(ContextCompat.getDrawable(context,R.drawable.selected_light_bg));
} else {
holder.imageView.setBackground(ContextCompat.getDrawable(context,R.drawable.inside_room_item_bg));
}
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context,"light clicked",Toast.LENGTH_LONG).show();
}
});
}
public void setSelectedPosition(int newPosition) {
this.selectedPosition = newPosition;
notifyDataSetChanged();
/* If you require better animations make use of notifyItemChanged() instead
* save selectedPosition value in a temp variable before swap
* and call notifyItemChanged() for both positions old and new
*/
}
#Override
public int getItemCount() {
return list.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private ImageView imageView;
public ViewHolder(#NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.inside_light_img);
}
}
}
And then instead of complicating your code your onPageSelected() should eb something like this
#Override
public void onPageSelected(int position) {
super.onPageSelected(position);
insideRoomAdapter.setSelectedPosition(position);
}
That's all, let us know if this answer helped solve your issue.

Disabling a RecyclerView

I'm facing the next problem.
I have a RecyclerView with the Adapter, the items, etc.
What I need is: Select an item in the recycler, change the color of that item, and then I have to disable the rest of the other items. It's like a RadioButton list.
I select one and disable the others. If I select again the same item, enable all the list.
I already have the onClick Button listener. I need to know if I have to reload again de list, If I have to loop and disable item by item, etc.
Thanks
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private List<Human> humans;
private HumanClick selectedHuman;
#Inject
public MyAdapter() {
}
public void init(List<Human> humanList, SelectedHumanClick humanClick){
this.humans = humanList;
this.humanClick = humanClick;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_Human, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final MyViewHolder holder, int position) {
final Human human = Humans.get(position);
holder.bind(Humans.get(position));
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
selectedHumanClick.onSelectedHumanClick(Human);
}
});
}
#Override
public int getItemCount() {
return humans != null ? Humans.size() : 0;
}
public final class MyViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.text_view_human_name)
TextView textView;
#BindView(R.id.image_view_profile)
ImageView imageViewProf;
#BindView(R.id.image_view_radio_btn)
ImageView imageViewRB;
private boolean isChecked = false;
public MyViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
public void bind(final Human Human) {
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
humanClick.onSelectedHumanClick(Human);
}
});
textView.setText(human.getName());
}
public void changeRBImage() {
if(!isChecked){
isChecked = true;
imageViewRB.setBackground(ContextCompat.getDrawable(imageViewRB.getContext(), R.drawable.selected));
}
else{
isChecked = false;
imageViewRB.setBackground(ContextCompat.getDrawable(imageViewRB.getContext(), R.drawable.not_selected));
}
}
}
My Recycler is defined inside a fragment here:
public class HumansFragment implenets HumanClick{
#BindView(R.id.recycler_humans)
RecyclerView humansRecyclerView;
#Inject
MyAdapter myAdapter;
.
.
.
public void loadHumans(List<Human> humans) {
myAdapter.init(Humans, this);
humansRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
humansRecyclerView.setAdapter(myAdapter);
}
#Override
public void humansClick(Human human) {
//TODO
}
}
I'm thinking in something like this, using setOnItemClickListener and check the position of the item clicked. The position is the index of the item clicked check the last event and new, if both are equal change color, if not dont do anything like disabling.
private ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
textView = (TextView)view.findViewById(android.R.id.text1);
}
#Override
public void onClick(View view) {
Toast.makeText(view.getContext(), "position = " + getLayoutPosition(), Toast.LENGTH_SHORT).show();
//go through each item if you have few items within recycler view
if(getLayoutPosition()==0){
//Do whatever you want here
}else if(getLayoutPosition()==1){
//Do whatever you want here
}else if(getLayoutPosition()==2){
}else if(getLayoutPosition()==3){
}else if(getLayoutPosition()==4){
}else if(getLayoutPosition()==5){
}
//or you can use For loop if you have long list of items. Use its length or size of the list as
for(int i = 0; i<exampleList.size(); i++){
}
}
}
Or something smaller
RecyclerView recyclerView = findViewById(R.id.recycler);
recyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(context, recyclerView ,new
RecyclerItemClickListener.OnItemClickListener() {
#Override public void onItemClick(View view, int position) {
// do whatever
}
#Override public void onLongItemClick(View view, int position) {
// do whatever
}
})
);

RecyclerView get View by position

I have a RecyclerView and each CardView contains a TextView and an ImageView. Whenever I click an item, I want to set the image visibility to VISIBLE and to set the previous clicked item image's visibility to INVISIBLE.
This is my Adapter class :
public class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.ViewHolder>{
private Context context;
private List<Category> lista;
private LayoutInflater layoutInflater;
private IncomeCategoryActivity activity;
private static final int CATEGORY_REQUEST=6;
private static final int ITEM_EDIT=1;
private static final int ITEM_DELETE=2;
private static final int EDIT_REQUEST=7;
private int current_pos=-1;
public CategoryAdapter(List<Category> lista, Context context, IncomeCategoryActivity activity) {
this.context = context;
this.lista = lista;
this.activity=activity;
layoutInflater=LayoutInflater.from(context);
}
#Override
public CategoryAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view=layoutInflater.inflate(R.layout.category_layout, parent, false);
ViewHolder viewHolder=new ViewHolder(view, activity);
return viewHolder;
}
#Override
public void onBindViewHolder(CategoryAdapter.ViewHolder holder, int position) {
holder.imageView.setImageURI(lista.get(position).getUri());
holder.textView.setText(lista.get(position).getCategory());
holder.position = position;
holder.category=lista.get(position);
if(holder.category.isChecked()==true){
holder.imageViewCheck.setVisibility(View.VISIBLE);
current_pos=position;
} else {
holder.imageViewCheck.setVisibility(View.INVISIBLE);
}
}
#Override
public int getItemCount() {
return lista.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnCreateContextMenuListener, MenuItem.OnMenuItemClickListener{
public ImageView imageView;
public TextView textView;
public ImageView imageViewCheck;
public int position;
public Category category;
public IncomeCategoryActivity activity;
public ViewHolder(View itemView, IncomeCategoryActivity activity) {
super(itemView);
this.activity=activity;
imageView=itemView.findViewById(R.id.customCategoryImageView);
textView=itemView.findViewById(R.id.customCategoryTextView);
imageViewCheck=itemView.findViewById(R.id.customCheckImageView);
itemView.setOnClickListener(this);
itemView.setOnCreateContextMenuListener(this);
}
#Override
public void onClick(View v) {
String aux=textView.getText().toString();
if(aux=="CATEGORIE NOUĂ"){
Intent intent=new Intent(context, CustomIncomeActivity.class);
activity.startActivityForResult(intent, CATEGORY_REQUEST);
}
else{
imageViewCheck.setVisibility(View.VISIBLE);
int pozitie_check=getLayoutPosition();
Intent intent=new Intent(context, AddIncomeActivity.class);
intent.putExtra("categorie_venit", aux);
intent.putExtra("position_check", pozitie_check);
activity.setResult(Activity.RESULT_OK, intent);
activity.finish();
}
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
menu.setHeaderTitle("Selectează acțiunea");
MenuItem edit=menu.add(0, ITEM_EDIT, 0, "Modifică");
MenuItem delete=menu.add(0, ITEM_DELETE, 0, "Șterge");
edit.setOnMenuItemClickListener(this);
delete.setOnMenuItemClickListener(this);
}
#Override
public boolean onMenuItemClick(MenuItem item) {
int position=getLayoutPosition();
if (item.getGroupId() == 0) {
if(item.getItemId()==ITEM_EDIT){
Category category=lista.get(position);
Intent intent=new Intent(activity, CustomIncomeActivity.class);
intent.putExtra("edit_icon", category.getUri());
intent.putExtra("edit_category", category.getCategory());
intent.putExtra("list_position", position);
activity.startActivityForResult(intent, EDIT_REQUEST);
}
else if(item.getItemId()==ITEM_DELETE){
lista.remove(position);
notifyDataSetChanged();
}
}
return true;
}
At this moment, whenever I click an item, there are two images VISIBLE on the RecyclerView: the clicked item's image and the previous clicked item's image. I think I need to get the previous View by its position and to manually set the visibility to INVISIBLE.
recycleView.getChildCount() and recycleView_parent.getChildAt() only gives the Adapter items which is shows only screen .
that means if your list has 200 items and the only 5 items shows on screen so we can find only 5 item with the help of recycleView
i am using one simple trick to solve the issue.
You can define Hashmap which hold your holder objects
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
ArrayList<Model> dataList;
Context context;
HashMap<Integer,ViewHolder> holderlist;
public MyAdapter(ArrayList<Model> dataList, Context context) {
this.context = context;
this.dataList = dataList;
holderlist = new HashMap<>();
}
And after that to save the holder in Hashmap
public void onBindViewHolder(final ViewHolder holder, final int position) {
if(!holderlist.containsKey(position)){
holderlist.put(position,holder);
}
Create a method in Adapter.
public MyListAdapter.ViewHolder getViewByPosition(int position) {
return holderlist.get(position);
}
Call this method from your Activity or whenever you want.
for (int i = 0; i < datalList.size(); i++) {
MyAdapter.ViewHolder holder = ((MyAdapter)recycleView.getAdapter()).getViewByPosition(i);
View view = holder.itemView;
TextView tv = view.findViewById(R.id.tv);
}
I have created the demo you can refer it and implement for single selection
recyclerView.setAdapter(new RecyclerView.Adapter() {
int selected_position = -1;
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new RecyclerView.ViewHolder(LayoutInflater.from(parent.getContext()).inflate(
R.layout.row_color_list,parent,false)) {
#Override
public String toString() {
return super.toString();
}
};
}
#Override
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, int position) {
ImageView imageView = holder.itemView.findViewById(R.id.image);
if(selected_position == position){
imageView.setVisibility(View.VISIBLE);
}else {
imageView.setVisibility(View.GONE);
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(selected_position != holder.getAdapterPosition()){
selected_position = holder.getAdapterPosition();
notifyDataSetChanged();
}
}
});
}
#Override
public int getItemCount() {
return 20;
}
});
You can do as following:
1) Declare a global variable:
private int selectedPos = -100; // Put any irrelevant number you want
2) Set selected position onClick() :
#Override
public void onClick(View v) {
selectedPos = getAdapterPosition();
}
3) Check selected postion and assign visibility inside onBindViewHolder():
#Override
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, int position) {
if(position == selectedPos){
holder.imageViewCheck.setVisibility(View.VISIBLE);
} else {
holder.imageViewCheck.setVisibility(View.INVISIBLE);
}
}
Try this code..
add this code into adapter class for handling click event..
OnItemClick onItemClick;
public void setOnItemClick(OnItemClick onItemClick) {
this.onItemClick = onItemClick;
}
public interface OnItemClick {
void getPosition(String data); //pass any data to shared it.
}
after bind method..
#Override
public void onBindViewHolder(final ItemViewHolder holder, final int position) {
// below code handle click event on recycler view item.
final String str=mStringList.get(position); // here your boject
if(holder.category.isChecked()==true){
holder.imageViewCheck.setVisibility(View.VISIBLE);
current_pos=position;
} else {
holder.imageViewCheck.setVisibility(View.INVISIBLE);
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onItemClick.getPosition(str); // pass your data.
}
});
}
after bind adapter into recycler view it means adapter not null then called below code..
adpater.setOnItemClick(new RecyclerViewAdpater.OnItemClick() {
#Override
public void getPosition(String data) {
// hear update your value for check into if condition.
data="sdfsdf";
adpater.notifyDataSetChanged();
}
});
and also read comments and also try to make custon class and access that object value and update after click it..
this code only how to handle click event into recycler view.

How to handle the recyclerview's items view inside activity?

In my app's recyclerview, each item have Play/Pause button to start/stop the media player. There are many events like downloading progress, play and stop the music. I'm going handle the events and update the UI immediately with broadcast receiver or in another way.
I do not know ho to access play or pause button in the activity.
#Override
public void onBindViewHolder(#NonNull final MyViewHolder holder, #SuppressLint("RecyclerView") final int position) {
holder.downloading.setVisibility(View.INVISIBLE);
holder.equalizer.setVisibility(View.INVISIBLE);
holder.btnPlay.setVisibility(View.VISIBLE);
holder.btnPause.setVisibility(View.INVISIBLE);
}
}
public class MyViewHolder extends RecyclerView.ViewHolder {
private ImageButton btnPlay, btnPause;
TextView title, id;
private ImageView trackImage, downloaded;
private GifImageView equalizer, downloading;
private CardView cardView;
public MyViewHolder(View itemView) {
super(itemView);
equalizer = itemView.findViewById(R.id.eq);
downloading = itemView.findViewById(R.id.loading);
btnPlay = itemView.findViewById(R.id.play);
btnPause = itemView.findViewById(R.id.pause);
btnPlay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MyOnClickListener.playOnClick(v, getAdapterPosition());
}
});
btnPause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MyOnClickListener.pauseOnClick(v, getAdapterPosition());
}
});
}
and inside activity, here how i can access to btnPlay, btnPause, ,... to set them visible or invisible in specefic times:
adapter = new Adapter(tracks, this, new Adapter.MyAdapterListener() {
#Override
public void playOnClick(View v, int position) {
if (//true) {
adapter.notifyItemChanged(currentItem, //?);
}
// hide some views in recyclerview's item and show some others
} else {
//...
}
}
update:
for (int i = 0; i < tracks.size(); i++) {
Track track = tracks.get(i);
if (track.getPlayStatus()) {
track.setPlayStatus(false);
//tell the RecyclerView this data position has changes
adapter.notifyItemChanged(i);
break;
}
}
Track track = tracks.get(position);
track.setPlayStatus(true);
adapter.notifyItemChanged(position);
and onBindViewHolder:
if (track.getPlayStatus()) {
holder.btnPlay.setVisibility(View.INVISIBLE);
holder.btnPause.setVisibility(View.VISIBLE);
//other sets you need
} else {
holder.btnPlay.setVisibility(View.VISIBLE);
holder.btnPause.setVisibility(View.INVISIBLE); }
You should keep track of current playing position to fix this.
The trick is to refresh both the currently playing view as well as new clicked view
public class Adapter extends RecyclerView.Adapter<Adapter.MyViewHolder> {
private int currentPlayingPosition = -1;
private MyOnClickListener mMyOnClickListener;
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// return viewholder
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
if (position == currentPlayingPosition) {
holder.btnPlay.setVisibility(View.GONE);
holder.btnPause.setVisibility(View.VISIBLE);
} else {
holder.btnPlay.setVisibility(View.GONE);
holder.btnPause.setVisibility(View.VISIBLE);
}
// other bindings
}
#Override
public int getItemCount() {
// return size
}
public void setMyOnClickListener(MyOnClickListener myOnClickListener) {
mMyOnClickListener = myOnClickListener;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
private ImageButton btnPlay, btnPause;
public MyViewHolder(View itemView) {
super(itemView);
// bind views
btnPlay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = getAdapterPosition();
int prev = currentPlayingPosition;
currentPlayingPosition = position;
if (prev >= 0)
notifyItemChanged(prev); // refresh previously playing view
notifyItemChanged(currentPlayingPosition);
mMyOnClickListener.playOnClick(v, position);
}
});
btnPause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = getAdapterPosition();
notifyItemChanged(position);
currentPlayingPosition = -1;
mMyOnClickListener.pauseOnClick(v, position);
}
});
}
}
private interface MyOnClickListener {
void playOnClick(View v, int position);
void pauseOnClick(View v, int position);
}
}
You don't need to pass anything to your Activity if all you need is to change items of a specific row.
Let's say your list item is clicked for playing. Then, you just set the corresponding isPlaying flag(please add it if it's not there yet) of your data item to true as below and notify the adapter there a change:
#Override
public void playOnClick(View v, int position) {
// reset playing state for a previous track if only one item can be played at a time
for (int i = 0; i < trackList.size(); i++) {
Track track = trackList.get(i);
if (track.isPlaying()) {
track.setIsPlaying(false);
//tell the RecyclerView this data position has changes
adapter.notifyItemChanged(i);
break;
}
}
Track track = trackList.get(position);
track.setIsPlaying(true);
//initiate the RecyclerView redrawal
adapter.notifyItemChanged(position);
}
Your pauseOnClick could be:
#Override
public void pauseOnClick(View v, int position) {
Track track = trackList.get(position);
track.setIsPlaying(false);
//initiate the RecyclerView redrawal
adapter.notifyItemChanged(position);
}
In your onBindViewHolder you change the item visibility based on the adapter data you're passing:
#Override
public void onBindViewHolder(#NonNull Wkdapter.Holder holder, int position) {
Track track = trackListList.get(position);
if (track.isPlaying()) {
holder.btnPlay.setVisibility(View.VISIBLE);
holder.btnPause.setVisibility(View.INVISIBLE);
//other sets you need
} else {
holder.btnPlay.setVisibility(View.INVISIBLE);
holder.btnPause.setVisibility(View.VISIBLE);
//your other inits
}
}
You can pass your widgets as arguments to your MyOnClickListener functions, like below:
MyOnClickListener.playOnClick(v, btnPlay, getAdapterPosition());
try something like this
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private CardView oneway_card, CardView;
private ImageView logo, arrow;
private Context context;
private List<Onwardflights> objectlist;
private TextView arrival, departure, duration, amount, flightcode, arr_text, stops, stops_text;
public ViewHolder(View itemView, Context context, List<Onwardflights> objectlist) {
super(itemView);
itemView.setOnClickListener(this);
this.context = context;
this.objectlist = objectlist;
*Initialize here*
logo = (ImageView) itemView.findViewById(R.id.oneway_logo);
arrival = (TextView) itemView.findViewById(R.id.oneway_arrtime);
}
Your onclick method
#Override
public void onClick(View view) {
int position = getAdapterPosition();
Log.i("Position", "Postion " + position + " is clicked");
oneway_card.setCardBackgroundColor(Color.parseColor("#E0FFFF"));
//your code
}

Categories

Resources