I am trying to select items in recylerview. When I click an item, a checkbox appears on that item and it is highlighted. But the problem is that when I scroll, the item which is highlighted goes to its original color but the checkbox image remains as it should. Why the highlighted color is gone but the image remains after scrolling, I want the items to keep their state after scrolling.
public static List<Model> item = new ArrayList<Model>()
#Override
public void onBindViewHolder(#NonNull MyAdapter.MyViewHolder holder, int
position) {
holder.bind(item.get(position));
//
public class MyViewHolder extends RecyclerView.ViewHolder{
public MyViewHolder(#NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.check);
public void bind(Model model) {
if (model.isChecked()){
imageView.setVisibility(View.VISIBLE);
itemView.setBackgroundColor(Color.GRAY);
model.setChecked(true);
} else {
imageView.setVisibility(View.GONE);
itemView.setBackgroundColor(Color.TRANSPARENT);
model.setChecked(false);
}
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Model s = item.get(getAdapterPosition());
if (!selectList.contains(s)){
selectList.add(s);
model.setChecked(true);
} else {
selectList.remove(s);
model.setChecked(false);
}
notifyItemChanged(getAdapterPosition());
}
});
public class Model {
private boolean isChecked = false;
public boolean isChecked() {
return isChecked;
}
public void setChecked(boolean checked) {
isChecked = checked;
}
}
Don't manually change the design in the onclick listener, just update your model (as you are already doing: model.setchecked(...) depending on state)
Then call Adapter.notifyItemChanged(getAdapterPosition())
This will force the adapter to reload the item, calling onBindViewHolder, where the design should be updated properly
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Model s = item.get(getAdapterPosition());
if (!selectList.contains(s)){
selectList.add(s);
model.setChecked(true);
} else {
selectList.remove(s);
model.setChecked(false);
}
adapter.notifyItemChanged(getAdapterPosition())
}
In the above example, replace "adapter" with a reference to your recylerview adapter
Related
I am trying to highlight clicked items in recylerview but as soon as when you scroll the highlighted items do not stay highlighted anymore. I do not know how to keep their state when scrolling. The implementation in the adapter class and given below:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyHolder>{
boolean isEnable = false;
List<ItemFiles> selectList = new ArrayList<>();
public MyAdapter.MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout._main,parent,false);
return new MyViewHolder(view);
public void onBindViewHolder(#NonNull MyAdapter.MyViewHolder holder, int
position) {
holder.item.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (isEnabled) {
ClickItem(holder);
}
}
private void ClickItem(MyHolder holder) {
ItemFiles s = files.get(holder.getAdapterPosition());
if (holder.highlightItem.getVisibility() == View.GONE){
holder.highlightItem.setVisibility(View.VISIBLE);
holder.highlightItem.setBackgroundColor(Color.LTGRAY);
selectList.add(s);
// this is what I tried to keep the highlighted state but no result
selectList.get(holder.getAdapterPosition()).setSelected(true);
} else {
holder.highlightItem.setVisibility(View.GONE);
holder.highlightItem.setBackgroundColor(Color.TRANSPARENT);
selectList.remove(s);
selectList.get(holder.getAdapterPosition()).setSelected(false);
}
}
}
How can I update the values in my Dataset from a Spinner selection in a RecyclerView? Should I be using LiveData and Room with notifyItemChange(), data binding, or something simpler? I have a Horseclass and a HorseData class. The number of items is static and the options for the variables are static. I do not need to add values or items, I just need to be able to select the variable WinPercentHorse for each item and have that value saved back to the dataset.
public class HorseAdapter extends RecyclerView.Adapter<HorseViewHolder> {
private AdapterView.OnItemSelectedListener onItemSelectedListener;
//we are storing all the horses in a list
private List<Horse> horseList;
//this context we will use to inflate the layout
private Context mCtx;
//getting the context and product list with constructor
public HorseAdapter(Context mCtx, List<Horse> horseList) {
this.mCtx = mCtx;
this.horseList = horseList;
}
#Override
public HorseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//inflating and returning our view holder
LayoutInflater inflater = LayoutInflater.from(mCtx);
View view = inflater.inflate(R.layout.item_layout, null);
return new HorseViewHolder(view);
}
#Override
public void onBindViewHolder(final HorseViewHolder holder, final int position) {
//getting the product of the specified position
Horse horse = horseList.get(position);
//binding the data with the viewholder views
holder.ViewWinPercent.setText(String.valueOf(horse.getWinPercentHorse()));
holder.imageView.setImageDrawable(mCtx.getResources().getDrawable(horse.getImgHorse()));
holder.ViewValueLine.setText(String.valueOf(horse.getValueOdds()));
holder.itemView.setTag(horse.getId());
holder.spinnerView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
// Update winPercent of item On selecting a spinner item
Toast.makeText(mCtx, "Spinner Selection =" + l + "item selected =" + position, Toast.LENGTH_SHORT).show();
//How to update the WinPercentHorse variable for this item in the horseList
//Then refresh the item notifyItemChange(position, object payload)?
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
}
#Override
public int getItemCount() {
return horseList.size();
}
public void setHorseList(List<Horse> horseList) {
this.horseList = horseList;
notifyDataSetChanged();
}
}
class HorseViewHolder extends RecyclerView.ViewHolder {
TextView ViewWinPercent, ViewValueLine;
ImageView imageView;
Spinner spinnerView;
public HorseViewHolder(View itemView) {
super(itemView);
ViewWinPercent = itemView.findViewById(R.id.winPercentHorse);
ViewValueLine = itemView.findViewById(R.id.valueLine);
imageView = itemView.findViewById(R.id.imgHorse);
spinnerView=itemView.findViewById(R.id.spinner);
}
}
when i click an item in Recyclerview every seventh item gets the effect.
onBindViewHolder:
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.channelName.setText(list.get(position).getChannnelName());
holder.linearLayoutChannelName.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
view.setBackgroundColor(Color.parseColor("#93bcff"));
}
});
}
public class ViewHolder extends RecyclerView.ViewHolder {
LinearLayout linearLayoutChannelName;
TextView channelName;
public ViewHolder(View itemView) {
super(itemView);
channelName = itemView.findViewById(R.id.tv_channel_name);
linearLayoutChannelName = itemView.findViewById(R.id.ll_channelname);
}
}
when i click an item every seventh item changes its backgroung color,and it repeats every seventh item in the list, and even when scrolling across the list the background color dissapears.
https://i.stack.imgur.com/oq2sb.jpg
https://i.stack.imgur.com/rOzQg.jpg
Don't use onClickListener in onBindViewHolder instead set it in onCreateViewHolder and create a member variable to set the selected item. You can do it like this.
int mSelectedItemPosition = -1;
// in your createViewHolder method
holder.linearLayoutChannelName.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
int position = holder.getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
mSelectedItemPosition = position;
notifyItemRangeChanged(0, yourList.size());
}
}
});
And in your bind view holder check selected item position and set the background color
if(mSelectedItemPosition == position){
view.setBackgroundColor(Color.parseColor("#yourColor"))
}else{
view.setBackgroundColor(Color.parseColor("originalColor"));
}
in fragment
mAdapter = new MessageAdapter(this);
mRV.setLayoutManager(new LinearLayoutManager(getActivity(),LinearLayoutManager.VERTICAL,false));
mRV.setItemAnimator(new DefaultItemAnimator());
DividerItemDecoration itemDecoration = new DividerItemDecoration.Builder()
.setOffsetLeft(ScreenUtil.dip2px(getActivity(), 60 + 10) + this.getResources().getDimensionPixelOffset(R.dimen.horizontal_margin))
.build(getActivity());
mRV.addItemDecoration(itemDecoration);
mRV.setItemViewCacheSize(15);
mRV.setAdapter(mAdapter);
in adapter
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new MessageItemHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.w_message_item,parent,false));
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((RVItemInterface)holder).setAdapter(this);
((RVItemInterface)holder).update(dataList.get(position),position);
}
in holder
public class MessageItemHolder extends RecyclerView.ViewHolder implements RVItemInterface{
private RoundAvatar mAvatar;
private TextView mTitle;
private TextView mContent;
private TextView mTime;
private BaseRVAdapter mAdapter;
private MsgDecorVo mMsgDecorVo;
...
#Override
public void update(Object obj, final int position) {
reset();
mMsgDecorVo = (MsgDecorVo) obj;
if(mMsgDecorVo.type == MsgDecorVo.TYPE_CATEGORY){
updateCategory();
MsgVo msgVo = mMsgDecorVo.msgVo;
if(msgVo.getMsg() == null || msgVo.getMsg().equals("")){
mContent.setVisibility(View.GONE);
}else {
mContent.setVisibility(View.VISIBLE);
mContent.setText(msgVo.getMsg());
}
if(msgVo.getTime() == 0){
mTime.setVisibility(View.GONE);
}else {
mTime.setVisibility(View.VISIBLE);
mTime.setText(TimeUtil.transformLong2DateString(msgVo.getTime()));
}
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dealCategoryClick();
}
});
}else if(mMsgDecorVo.type == MsgDecorVo.TYPE_CONVERSATION){
...
mContent.setText(ImUtil.getMsgContent(message));
mTime.setText(TimeUtil.transformLong2DateString(message.getMsgTime()));
if(chatUserVo != null){
..
}else {
..
}
}
}
//
private void updateCategory(){
...
}
//
private void dealCategoryClick(){
...
}
#Override
public void setAdapter(RecyclerView.Adapter adapter) {
mAdapter = (BaseRVAdapter) adapter;
}
#Override
public void reset() {
mAvatar.setOnClickListener(null);
mAvatar.setAvatar(R.drawable.avatar_default_circle);
mAvatar.hideTagBottom();
mAvatar.hideTagTop();
}
}
these code in holder
mContent.setText(ImUtil.getMsgContent(message));
mTime.setText(TimeUtil.transformLong2DateString(message.getMsgTime()));
has run
but when I scrolled,some of items doesn't show correctly ,the time and content was gone!
if I notify the recyclerview ,it goes right, and if i scroll again,it will still be wrong
just like the image,you can see some items' (time & content) was gone!
http://g.picphotos.baidu.com/album/s%3D900%3Bq%3D90/sign=297cc7510946f21fcd345253c61f1a5d/a686c9177f3e6709378bcc5538c79f3df9dc5595.jpg "tooltip"
Well, you don't have the full code but I assume it is happening because you are not resetting your view states properly.
For Instance, in your updateCode, if type = TYPE_CATEGORY, you set the mTime's visibility depending on whether getTime is 0 or not. But as you scroll, that row might be re-used for
TYPE_CONVERSATION in which case, mTime's visibility will NOT be updated.
I need to create a custom RadioButton without circle. Its a very simple class that extends Label and implements Toggle.
I added a mouse clicked handler :
private class MouseClickedHandler implements EventHandler<MouseEvent> {
#Override
public void handle(MouseEvent t) {
final Toggle toggle = (Toggle) t.getSource();
if (!toggle.isSelected()) {
getToggleGroup().selectToggle(toggle);
}
}
}
My problem is to set a default selected radio button.
If on one of the RadioButton I call setSelected(true) after its creation and after adding it to a ToggleGroup, when I launch the application if I click on other radio buttons in the group, the ToggleGroup does its job of deselecting except for that default one. I always end up with 2 radio buttons selected, the one on which I called setSelected(true) directly, and the one currently selected by a click.
I corrected it - Complete code :
public class RadioBtn extends Label implements Toggle {
private ObjectProperty<ToggleGroup> toggleGroup = null;
private BooleanProperty selectedProperty = null;
public RadioBtn {
initHandlers();
}
#Override
public ToggleGroup getToggleGroup() {
return toggleGroupProperty().get();
}
#Override
public void setToggleGroup(ToggleGroup tg) {
if (getToggleGroup() == null) {
toggleGroupProperty().set(tg);
}
getToggleGroup().getToggles().add(this);
}
#Override
public ObjectProperty<ToggleGroup> toggleGroupProperty() {
if (toggleGroup == null) {
toggleGroup = new SimpleObjectProperty<>();
}
return toggleGroup;
}
#Override
public boolean isSelected() {
return selectedProperty().get();
}
#Override
public void setSelected(boolean bln) {
selectedProperty().set(bln);
}
#Override
public BooleanProperty selectedProperty() {
if (selectedProperty == null) {
selectedProperty = new SimpleBooleanProperty();
}
return selectedProperty;
}
protected void initHandlers() {
if (getToggleGroup() != null) {
setOnMouseClicked(new ToggleGroupHandler());
}
}
private class ToggleGroupHandler implements EventHandler<MouseEvent> {
#Override
public void handle(MouseEvent t) {
final Toggle toggle = (Toggle) t.getSource();
if (!toggle.isSelected()) {
/*if(getToggleGroup().getSelectedToggle() != null) {
getToggleGroup().getSelectedToggle().setSelected(false);
}*/
getToggleGroup().selectToggle(toggle);
}
}
}
}