I am wondering that my images and color of layouts shuffling when i scrolls downwards or upwards, I created cardview using recyclerview. and set an image(changes color on cl
I have created a working example of what you are trying to accomplish. The source of the errors you experience is mostly that you don't understand view recycling. I am not going to explain the whole thing to you now, but anyway here is the example:
For the example I used this layout for each row:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
android:id="@+id/background"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="80dp">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
</FrameLayout>
I used this model:
public class ExampleModel {
private final int mColor;
private final String mText;
public ExampleModel(int color, String text) {
mColor = color;
mText = text;
}
public int getColor() {
return mColor;
}
public String getText() {
return mText;
}
}
And this view holder:
public class ExampleViewHolder extends RecyclerView.ViewHolder {
private final FrameLayout mBackground;
private final TextView mTextView;
public ExampleViewHolder(View itemView) {
super(itemView);
mBackground = (FrameLayout) itemView.findViewById(R.id.background);
mTextView = (TextView) itemView.findViewById(R.id.textView);
}
public void bind(ExampleModel model) {
mBackground.setBackgroundColor(model.getColor());
mTextView.setText(model.getText());
}
}
As you can see nothing special, the Adapter
implementation is equally simple:
public class ExampleAdapter extends RecyclerView.Adapter<ExampleViewHolder> {
private final LayoutInflater mInflater;
private final List<ExampleModel> mModels;
public ExampleAdapter(Context context, List<ExampleModel> models) {
mInflater = LayoutInflater.from(context);
mModels = models;
}
@Override
public ExampleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View itemView = mInflater.inflate(R.layout.item_example, parent, false);
return new ExampleViewHolder(itemView);
}
@Override
public void onBindViewHolder(ExampleViewHolder holder, int position) {
final ExampleModel model = mModels.get(position);
holder.bind(model);
}
@Override
public int getItemCount() {
return mModels.size();
}
}
And you use the whole thing like this:
final Random mRandom = new Random(System.currentTimeMillis());
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
final List<ExampleModel> models = new ArrayList<>();
for (int i = 0; i < 100; i++) {
final int randomColor = generateRandomPastelColor();
models.add(new ExampleModel(randomColor, String.valueOf(i)));
}
final ExampleAdapter adapter = new ExampleAdapter(getActivity(), models);
recyclerView.setAdapter(adapter);
}
public int generateRandomPastelColor() {
final int baseColor = Color.WHITE;
final int red = (Color.red(baseColor) + mRandom.nextInt(256)) / 2;
final int green = (Color.green(baseColor) + mRandom.nextInt(256)) / 2;
final int blue = (Color.blue(baseColor) + mRandom.nextInt(256)) / 2;
return Color.rgb(red, green, blue);
}
This should do what you are looking for and you can use it as an example of how to implement your Adapter
.
I got the same problem ,when i used the radioButton in my listView row, I solved it. As in every scrolling the Cache is cleared, you have to store the changed data in every row. just check my code
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
// if(position==0)
// Toast.makeText(context, ""+QuestionViewPageAdapter.mRadioGroupData, Toast.LENGTH_SHORT).show();
final ViewHolder viewHolder;
View row=convertView;
radioButton=new RadioButton[Integer.parseInt(mNoOfCategoryGreading)];
LayoutInflater inflater =LayoutInflater.from(context);//(LayoutInflater)context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.question_row, parent, false);
viewHolder=new ViewHolder();
viewHolder.tv_qContent=(TextView)row.findViewById(R.id.tv_question);
viewHolder.rg=(RadioGroup)row.findViewById(R.id.rgrp);
for(int i=0;i<Integer.parseInt(mNoOfCategoryGreading);i++)
{
radioButton[i]=new RadioButton(context);
radioButton[i].setLayoutParams(new RadioGroup.LayoutParams(0, LayoutParams.WRAP_CONTENT,1f));
//1f for layout_weight="1"
radioButton[i].setId(i);
radioButton[i].setText(""+(i+1));
viewHolder.rg.addView(radioButton[i]);
}
row.setTag(viewHolder);
for(int i=0;i<QuestionViewPageAdapter.mRadioGroupData.size();i++){
int p=Integer.parseInt(""+QuestionViewPageAdapter.mRadioGroupData.get(i).get("position"));
String id=QuestionViewPageAdapter.mRadioGroupData.get(i).get("Id");
if(p!=-1 && id.equals(""+data.get(position).get(AppData.question_Set_category_QuestionID)))
{//radioButton[p].setSelected(true);
viewHolder.rg.check(p-1);}
//Toast.makeText(context, "Yes "+p, Toast.LENGTH_LONG).show();}
}
viewHolder.tv_qContent.setText((position+1)+". "+data.get(position).get(AppData.question_Set_category_QuestionContent));
viewHolder.tv_qContent.setTypeface(typeface_muso_regular300);
viewHolder.rg.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
// TODO Auto-generated method stub
String s=data.get(position).get(AppData.question_Set_category_QuestionID);
isAvailabel(s);
int radioButtonID = viewHolder.rg.getCheckedRadioButtonId();
View radioButton = viewHolder.rg.findViewById(radioButtonID);
int idx = viewHolder.rg.indexOfChild(radioButton);
HashMap<String, String> map=new HashMap<String, String>();
map.put("position", ""+(idx+1));
map.put("Id", ""+data.get(position).get(AppData.question_Set_category_QuestionID));
map.put("CategoryId", ""+mCategoryId);
QuestionViewPageAdapter.mRadioGroupData.add(map);
}
});
return row;
}
private void isAvailabel(String qId){
for(int i=0;i<QuestionViewPageAdapter.mRadioGroupData.size();i++){
if(qId.equals(QuestionViewPageAdapter.mRadioGroupData.get(i).get("Id"))){
position=i;
QuestionViewPageAdapter.mRadioGroupData.remove(i);
}
}
}
class ViewHolder {
TextView tv_qContent ,tv_1,tv_2,tv_3;
RadioGroup rg;
RadioButton rBtn1,rBtn2,rBtn3,rBtn4,rBtn5;
}
In my case overriding getItemId
and setting sethasStableIds
to true solved the shuffling issue.
in adapter:
@Override
public long getItemId(int position) {
Object listItem = feeds.get(position);
return listItem.hashCode();
}
in main activity/fragment :
adapter = new FeedAdapter(feeds, getContext());
adapter.setHasStableIds(true);