How to avoid duplicate data in recyclarview when scrolling recycler view - android

We are using recyclarview for first time. My problem is when scrolling recyclar duplicate data is adding to view. In Below Code:
public class ProductOptions_RecyclerAdapter extends RecyclerView.Adapter<ProductOptions_ListRowHolder> {
private ArrayList<Product_Details> storeItemList;
HashMap<String, List<Product_Details>> product_items = new HashMap<String, List<Product_Details>>();
private Context mContext;
List<String> arrlist_skuitemName = new ArrayList<String>();
List<String> arrlist_skuitemLabel = new ArrayList<String>();
public ProductOptions_RecyclerAdapter(Context context, List<String> arrlist_skuitemName, List<String> arrlist_skuitemLabel, HashMap<String, List<Product_Details>> product_items) {
this.product_items = product_items;
this.mContext = context;
this.arrlist_skuitemName = arrlist_skuitemName;
this.arrlist_skuitemLabel = arrlist_skuitemLabel;
}
#Override
public ProductOptions_ListRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_productoptions, null);
ProductOptions_ListRowHolder store = new ProductOptions_ListRowHolder(v);
return store;
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public void onBindViewHolder(ProductOptions_ListRowHolder holder, int position) {
holder.name.setText(Html.fromHtml(arrlist_skuitemName.get(position)));
holder.label.setText(Html.fromHtml(arrlist_skuitemLabel.get(position)));
List<Product_Details> items = product_items.get(arrlist_skuitemName.get(position));
Log.d("listdata","min postion"+position+" / "+items.size());
for (int i = 0; i < items.size(); i++) {
RadioButton[] rb = new RadioButton[items.size()];
Product_Details pd = items.get(i);
rb[i] = new RadioButton(mContext);
rb[i].setTextColor(ColorStateList.valueOf(Color.parseColor("#000000")));
rb[i].setButtonTintList(ColorStateList.valueOf(Color.parseColor("#ff9900")));
holder.rd_option.addView(rb[i]);
rb[i].setText(pd.getName());
TextView tv = new TextView(mContext);
LinearLayout.LayoutParams buttonParams1 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
buttonParams1.gravity = Gravity.END;
tv.setLayoutParams(buttonParams1);
tv.setText(pd.getSalePrice());
tv.setTextSize(15);
// tv.setGravity(Gravity.RIGHT| Gravity.END);
//holder.ll_priceitem.addView(tv);
holder.rd_option.addView(tv);
}
holder.rd_option.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
int radioButtonID = group.getCheckedRadioButtonId();
RadioButton radioButton = (RadioButton) group.findViewById(radioButtonID);
Toast.makeText(mContext,radioButton.getText(),Toast.LENGTH_LONG).show();
}
});
View.OnClickListener clickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
ProductOptions_ListRowHolder tt = (ProductOptions_ListRowHolder) v.getTag();
int pos = tt.getPosition();
}
};
//Handle click event on both title and image click
holder.rd_option.setOnClickListener(clickListener);
holder.rd_option.setTag(holder);
// notifyDataSetChanged();
}
#Override
public int getItemCount() {
return (null != product_items ? product_items.size() : 0);
}
#Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
}
In this Product_Details is a model class.Here we are trying to add radiobuttons dynamically based on service response i.e, added to HashMap(product_items).
When we are scrolling recyclar view automatic duplicates are adding.
For activity created data is correct.when scrolling duplicates adding.
Please Guide us, where we are going wrong?
Thanks in Advance.

Related

how to control listview to reload.

I face a problem in list view. In my list view have edit text and text view. When i scroll the list my data that is entered in text view has lost the value and show the default value. i have two button in list view i increase the quantity and scroll the list for next product when i come back text view lost the value and show default value 1 . And when i open keyboard for enter data then same issue . please help me.
And its my code
Custom Adapter
private List<ShowProducts> listShowProducts;
private Context context;
private int resource;
private String condition;
String uri;
private static final String TAG = "CustomAdapter";
int i = 0;
float total;
ListView listView;
TextView tvTotal;
float sum = 0;
public CustomAdapter(#NonNull Context context, #LayoutRes int resource, List<ShowProducts> objects) {
super(context, resource, objects);
this.context = context;
this.resource = resource;
this.listShowProducts = objects;
}
#Override
public int getCount() {
return super.getCount();
}
#Nullable
#Override
public Object getItem(int position) {
return super.getItem(position);
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View view = LayoutInflater.from(context).inflate(resource, parent, false);
{
final ShowProducts showProducts = listShowProducts.get(position);
ImageView imageView = (ImageView) view.findViewById(R.id.imageViewOfSelecteditem);
ImageView plus = (ImageView) view.findViewById(R.id.imageviewPlus);
ImageView minus = (ImageView) view.findViewById(R.id.imageviewminus);
TextView tvSetNameOfSeletedItem = (TextView) view.findViewById(R.id.tvSetNameOfSeletedItem);
TextView tvSetSizeOfSeletedItem = (TextView) view.findViewById(R.id.tvSetSizeOfSeletedItem);
TextView tvSetPriceOfSeletedItem = (TextView) view.findViewById(R.id.tvSetPriceOfSeletedItem);
final TextView tvQunatitySetOfSelectedItem = (TextView) view.findViewById(R.id.tvQunatitySetOfSelectedItem);
for (int a = 0; a < 10; a++) {
Log.d(TAG, "onnnnView: ");
}
Log.d(TAG, "getView: +++++");
tvSetNameOfSeletedItem.setText(showProducts.getProduct_name().toString());
tvSetSizeOfSeletedItem.setText(showProducts.getSize_name());
tvSetPriceOfSeletedItem.setText(String.valueOf(showProducts.getSize_price()).toString());
uri = showProducts.getProduct_photo().toString();
Picasso.with(context).load(uri).into(imageView);
plus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int a = Integer.parseInt(tvQunatitySetOfSelectedItem.getText().toString());
a++;
Log.d(TAG, "getView: ");
if (a <= showProducts.getSize_quantity()) {
tvQunatitySetOfSelectedItem.setText(String.valueOf(a).toString());
tvTotal = (TextView) ((Activity) context).findViewById(R.id.tvTotalShow);
float price = Float.parseFloat(tvTotal.getText().toString());
sum = price + showProducts.getSize_price();
tvTotal.setText(String.valueOf(sum));
}
}
});
minus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int a = Integer.parseInt(tvQunatitySetOfSelectedItem.getText().toString());
a--;
if (a > 0)
{
tvQunatitySetOfSelectedItem.setText(String.valueOf(a).toString());
tvTotal = (TextView) ((Activity) context).findViewById(R.id.tvTotalShow);
float price = Float.parseFloat(tvTotal.getText().toString());
sum = price - showProducts.getSize_price();
tvTotal.setText(String.valueOf(sum));
}
}
});
}
return view;
}
And activity code
public class SelectedProductFromShopingCartShow extends AppCompatActivity {
ArrayList<ShowProducts> arrayList = new ArrayList<>();
String condition = "SelectedItemsFromShoppingCart";
CustomAdapter customAdapter;
ListView listView;
TextView tvTotal;
EditText etDiscount;
int total;
float sum = 0;
Button discount;
private static final String TAG = "SelectedProductFromShop";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_selected_product_from_shoping_cart_show);
listView = (ListView) findViewById(R.id.listViewSelectedItemsOfShopingCart);
tvTotal = (TextView) findViewById(R.id.tvTotalShow);
etDiscount = (EditText) findViewById(R.id.etDiscount);
arrayList = (ArrayList<ShowProducts>) getIntent().getSerializableExtra("selectedList");
ShowProducts showProducts = arrayList.get(0);
Log.d(TAG, "onnnnCreate: " + showProducts.getProduct_name());
customAdapter = new CustomAdapter(SelectedProductFromShopingCartShow.this, R.layout.show_selected_item_of_shopingcart, condition, arrayList);
listView.setAdapter(customAdapter);
getTotalListView();
Log.d(TAG, "onnnnCreate: Before inner class");
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {
AlertDialog.Builder builder = new AlertDialog.Builder(SelectedProductFromShopingCartShow.this);
builder.setTitle("Delete this product");
builder.setMessage("Are you sure you want to delete it?");
builder.setCancelable(true);
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
arrayList.remove(position);
customAdapter.notifyDataSetChanged();
Toast.makeText(SelectedProductFromShopingCartShow.this, "item deleted", Toast.LENGTH_SHORT).show();
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.setIcon(android.R.drawable.ic_dialog_alert);
builder.show();
return true;
}
});
}
public void getTotalListView() {
sum = 0;
for (int i = 0; i < arrayList.size(); i++) {
ShowProducts showProducts = arrayList.get(i);
sum = sum + showProducts.getSize_price();
tvTotal.setText(String.valueOf(sum));
}
}
And watch this video for understand problems
https://youtu.be/WAjtRkI5dl4
You need to follow viewholder pattern. It will resolve your issue. You can check it here https://developer.android.com/training/improving-layouts/smooth-scrolling.html
The only place you're keeping count is in the view. You should make your count a field in the list item ShowProducts and create a getter & setter. For example, in the plus onClickListener, instead of
int a = Integer.parseInt(tvQunatitySetOfSelectedItem.getText().toString());
a++;
You'll have
// for example, in the `plus` listener
int a = showProducts.getCount();
a++;
showProducts.setCount(a);
And don't forget
notifyDataSetChanged();

How to modify only one row at a time while using Customized ListView

I have used Customized ListView And not ExtendedListView. i have taken relative layout in order to show it as sub_list. By default i have set the visibilty of this sub_list relative layout as GONE. And on the click of any listItem that relative layout(by default set as gone) will appear on the screen respectively. But When I click on any of the rows the sub_list appear for each row simultaneously. What i want is that it should be shown only for one row at a time. I have already checked this similar [question]: How to modify only one row at a time in Listview? and modified my code but still i am unable to achieve my goal.
Here is my pieace of code:
public class CustomAdapter extends BaseAdapter {
Activity context;
ArrayList<String> s_date,c_number,d_ration,s_time,download_path,a_number,a_name,dt_number;
int flag=0,temp=1,position;
String mUrl;
int posview;
private int selectedIndex;
CustomAdapter(Activity context, ArrayList<String> start_date, ArrayList<String> caller_number, ArrayList<String> duration,ArrayList<String> start_time, ArrayList<String> download_path, ArrayList<String> agent_number, ArrayList<String> agent_name,ArrayList<String> dt_num)
{
this.context=context;
this.s_date=start_date;
this.c_number=caller_number;
this.d_ration=duration;
this.s_time=start_time;
this.download_path=download_path;
this.a_number=agent_number;
this.a_name=agent_name;
this.dt_number=dt_num;
selectedIndex = -1;
}
public void setSelectedIndex(int ind)
{
selectedIndex = ind;
notifyDataSetChanged();
}
#Override
public int getCount() {
return s_date.size();
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int position) {
return position;
}
public View getView(final int pos, final View v, ViewGroup g)
{
//LayoutInflater l=context.getLayoutInflater();
//View rowView=l.inflate(R.layout.log_layout,null,true);
posview=pos;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View row = inflater.inflate(R.layout.list_item, g, false);
TextView start_date = (TextView) row.findViewById(R.id.start_date);
start_date.setText(s_date.get(pos));
TextView caller_number = (TextView) row.findViewById(R.id.caller_number);
caller_number.setText(c_number.get(pos));
TextView duration = (TextView) row.findViewById(R.id.duration);
duration.setText(d_ration.get(pos));
TextView start_time = (TextView) row.findViewById(R.id.start_time);
start_time.setText(s_time.get(pos));
TextView agent_name = (TextView) row.findViewById(R.id.agent_name);
agent_name.setText(a_name.get(pos));
TextView agent_number = (TextView) row.findViewById(R.id.agent_number);
agent_number.setText(a_number.get(pos));
TextView dt_numb=(TextView)row.findViewById(R.id.dt_number);
dt_numb.setText("MHL No. -"+dt_number.get(pos));
RelativeLayout r = (RelativeLayout)row.findViewById(R.id.sub_layout);
r.setVisibility(position == posview ? View.VISIBLE : View.GONE);
row.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
posview=pos;
notifyDataSetChanged();
}
});
return row;
}
}
Previously my code was:
row.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//setSelectedIndex(view.getId());
RelativeLayout sub_list = (RelativeLayout) row.findViewById(R.id.sub_layout);
sub_list.setVisibility(View.VISIBLE);
//notifyDataSetChanged();
}
});
I am getting all the data dynamically. This is how i'm using the adapter in MainActivity:
CustomAdapter a=new CustomAdapter(MainScreen.this,start_date,caller_number,duration,start_time,download_path,agent_number,agent_name,dt_number);
data_list.setAdapter(a);
In this start_date caller_number etc are arraylist.This is how i'm parsing data in MainActivity.
JSONObject responseObject = new JSONObject(response);
JSONObject callLog = responseObject.getJSONObject("call_log");
Iterator<String> phoneNumbers = callLog.keys();
while (phoneNumbers.hasNext()) {
String number = phoneNumbers.next();
// Log.v("string number",number);
JSONObject numberLog = callLog.getJSONObject(number);
Iterator<String> callEntries = numberLog.keys();
while (callEntries.hasNext()) {
String entry = callEntries.next();
//Log.v("unique keys are",entry);
JSONObject entryObject = numberLog.getJSONObject(entry);
jsonArray.put(entryObject.getString("start_date"));
jsonArray.put(entryObject.getString("start_time"));
jsonArray.put(entryObject.getString("end_date"));
jsonArray.put(entryObject.getString("end_time"));
jsonArray.put(entryObject.getString("recording_path"));
String startDate = entryObject.getString("start_date");
start_date.add(startDate);
String startTime = entryObject.getString("start_time");
start_time.add(startTime);
String endDate = entryObject.getString("end_date");
String endTime = entryObject.getString("end_time");
String call_sdate = entryObject.getString("call_sdate");
String call_edate = entryObject.getString("call_edate");
String call_type = entryObject.getString("call_type");
String caller = entryObject.getString("caller");
caller_number.add(caller);
String duartion = entryObject.getString("duartion");
String call_duartion = entryObject.getString("call_duartion");
duration.add(call_duartion);
String dtmf = entryObject.getString("dtmf");
String dt_num = entryObject.getString("dt_number");
dt_number.add((dt_num));
String recording_path = entryObject.getString("recording_path");
download_path.add(recording_path);
String agent_mobile = entryObject.getString("agent_mobile");
agent_number.add(agent_mobile);
String a_name = entryObject.getString("agent_name");
agent_name.add(a_name);
Create two variables :
Map<Integer, View> lastExpanded = new HashMap<>();
int lastExpandedPosition =-1;
Create a function in your adapter :
private void expand(int i, View layout){
if(!lastExpanded.containsKey(i)){
layout.setVisibility(View.VISIBLE);
lastExpanded.put(i, layout);
if(lastExpanded.containsKey(lastExpandedPosition)){
expand(lastExpandedPosition, lastExpanded.get(lastExpandedPosition));
}
lastExpanded.remove(lastExpandedPosition);
lastExpandedPosition = i;
lastExpanded.put(lastExpandedPosition, layout);
}else{
layout.setVisibility(View.GONE);
lastExpandedPosition = -1;
lastExpanded.remove(i);
}
}
now,
final RelativeLayout layout = (RelativeLayout) row.findViewById(R.id.b);
layout.setVisibility(View.GONE);
row.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
expand(i, layout);
}
});
You can acheive this easily with expandable listview and your adapter class should extend BaseExpandableListAdapter
in activity
private int lastExpandedPosition = -1;
expListView.setOnGroupClickListener(new OnGroupClickListener() {
#Override
public boolean onGroupClick(ExpandableListView parent, View v,
final int groupPosition, long id) {
// TODO Auto-generated method stub
if (parent.isGroupExpanded(groupPosition)) {
expListView
.collapseGroup(lastExpandedPosition);
} else {
expListView.expandGroup(groupPosition);
}
return true;
}
});
expListView.setOnGroupExpandListener(new OnGroupExpandListener() {
#Override
public void onGroupExpand(int groupPosition) {
// TODO Auto-generated method stub
if (lastExpandedPosition != -1
&& groupPosition != lastExpandedPosition) {
expListView
.collapseGroup(lastExpandedPosition);
}
lastExpandedPosition = groupPosition;
}
});
You have to use ArrayList which contents as your data while you click on the item.
public class DataModel{
private String s_date,c_number,d_ration,s_time,download_path,a_number,a_name,dt_number;
private boolean isChildVisible;
..... create it's setter and getter methods.
}
when itemclick is called that time you should update the flag of isChildVisible for that position.
public void setSelectedIndex(int ind)
{
arrayListDataModel.get(ind).setIsChildVisible(true);
notifyDataSetChanged();
}
In your getview method :
public View getView(final int pos, final View v, ViewGroup g)
{
----your initialization code.
RelativeLayout r = (RelativeLayout)row.findViewById(R.id.sub_layout);
r.setVisibility(arrayListDataModel.get(pos).isChildVisible() ? View.VISIBLE : View.GONE);
row.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
setSelectedIndex(pos);
}
});
return row;
}
parse the data with below code :
final ArrayList<DataModel> dataModelList = new ArrayList<>();
while (callEntries.hasNext()) {
DataModel dataModel = new DataModel();
String entry = callEntries.next();
//Log.v("unique keys are",entry);
JSONObject entryObject = numberLog.getJSONObject(entry);
jsonArray.put(entryObject.getString("start_date"));
jsonArray.put(entryObject.getString("start_time"));
jsonArray.put(entryObject.getString("end_date"));
jsonArray.put(entryObject.getString("end_time"));
jsonArray.put(entryObject.getString("recording_path"));
String startDate = entryObject.getString("start_date");
dataModel.setStartDate(startDate);
String startTime = entryObject.getString("start_time");
dataModel.setStartTime(startTime);
...... same as above for others fields
dataModelList.add(dataModel);
}

Listview postion not working properly

I have list view. I want to change color of clicked row. But only 0,1 and 2 indexes are correctly colored others are not working properly likewise if i clicked on 4th row the 5th one row color changes and sometimes if i clicked on 7th row then none of row is colored. Please Help
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,final int position, long id) {
for (int i = 0; i < lv.getChildCount(); i++) {
if(position == i ){
lv.getChildAt(i).setBackgroundColor(Color.BLUE);
}else{
lv.getChildAt(i).setBackgroundColor(Color.TRANSPARENT);
}
}
public abstract class CustomAdapter extends BaseAdapter implements SeekBar.OnSeekBarChangeListener {
Context context;
ArrayList<HashMap<String, String>> countryList;
ArrayList<HashMap<String, String>> mStringFilterList;
LayoutInflater inflter;
public ImageView img2,img3;
Handler mHandler = new Handler();
SeekBar songProgressBar;
SelfUpdatingSeekbar self;
public boolean isStarted = true;
public static final int UPDATE_FREQUENCY = 500;
public static final int STEP_VALUE = 4000;
public final Handler handler = new Handler();
public final Runnable updatePositionRunnable = new Runnable() {
public void run() {
updatePosition();
}
};
public CustomAdapter(Context applicationContext, ArrayList<HashMap<String, String>> countryList) {
this.context = applicationContext;
this.countryList = countryList;
mStringFilterList = countryList;
inflter = (LayoutInflater.from(applicationContext));
}
#Override
public int getCount() {
return countryList.size();
}
public void updateData(ArrayList<HashMap<String, String>> countryList) {
this.countryList = countryList;
notifyDataSetChanged();
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(final int position, View view, ViewGroup viewGroup) {
view = inflter.inflate(R.layout.list_itemss, null);
view.setTag(position);
String hello = String.valueOf(countryList.get(position));
String s = hello;
int s1 = s.lastIndexOf("=");
int s2 = s.lastIndexOf("}");
strSub = s.substring(s1+1,s2/*s.lastIndexOf("=")*/);
Log.d("Hello",hello);
String henno1 = String.valueOf(hello.length());
Log.d("hellya",strSub);
TextView country = (TextView) view.findViewById(R.id.textView);
country.setText(strSub);
uniqueItemIdCount = countryList.size();
Log.d("PrintIdss", String.valueOf(uniqueItemIdCount));
ImageView twitt = (ImageView)view.findViewById(R.id.button5);
twitt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
TweetComposer.Builder builder = new TweetComposer.Builder(context)
.text(strSub);
builder.show();
}
});
ImageView fb = (ImageView)view.findViewById(R.id.button6);
fb.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ShareLinkContent linkContent = new ShareLinkContent.Builder()
.setContentTitle(strSub)
.setContentDescription(
"Top Hollywood Songs")
.setContentUrl(Uri.parse("http://www.moremovies.com/"))
.build();
shareDialog.show(linkContent);
}
});
songProgressBar = (SeekBar) view.findViewById(R.id.songProgressBar);
songProgressBar.setOnSeekBarChangeListener(this);
songCurrentDurationLabel = (TextView)view.findViewById(R.id.songCurrentDurationLabel);
songTotalDurationLabel = (TextView)view.findViewById(R.id.songTotalDurationLabel);
img2 = (ImageView)view.findViewById(R.id.button3);
img2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int songIndex = position;
String hellos = String.valueOf(countryList.get(songIndex));
int s1 = hellos.lastIndexOf("=");
int s2 = hellos.lastIndexOf("}");
String strSubs = hellos.substring(s1+1,s2/*s.lastIndexOf("=")*/);
selelctedFile.setText(strSubs);
currentSongIndex=songIndex;
playSong(currentSongIndex);
}
});
}
You have to manage the position and the background of yourself because in your adapter as you are reusing the cell. Kindly check your adapter you will get it.
And to achieve what you want. You have to update your adapter and implement the click listener in the Adapter view.
Try to subtract the position of your listview:
for (int i = 0; i < lv.getChildCount(); i++) {
if(position - lv.getFirstVisiblePosition() == i ){ //<-Here
lv.getChildAt(i).setBackgroundColor(Color.BLUE);
}else{
lv.getChildAt(i).setBackgroundColor(Color.TRANSPARENT);
}
}
You need to implement the two background options, because the adapter will reuse your layout.
So you need to keep track of the selected items (not layouts), as i see you are using a HashMap to populate your adapter so, create a List with the selected positions and when you are populating your adapter do something like :
//Globals Variables
List<int> SelectedList = new ArrayList<>();
//On select event
SelectedList.add(position);
//On deselect event
SelectedList.remove(position);
//On get view
if(SelectedList.contains(position){
// Background selected
}else{
// Explicit set the background to the default
}
If you want to start with play buttons and on click change to pause the one clicked and all others back to play then inside your adapter where you initialize the play/pause button do :
playPause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,final int position, long id) {
for (int i = 0; i < lv.getChildCount(); i++) {
Button PlayPause = v.findViewById(R.id.play_pause_button)
ButtonPlayPause.setImageResource("play resource")
}
playPause.setImageResource("pause resource")
}
}
}
});
Code may have some syntax errors but you get the idea.

RecyclerView items positions change or removed when scrolling

I have a problem that I have been trying to solve for too long but I can't know what causes the problem.
I have a marks list that contains Test objects and subject strings that I use as sections between marks, I use getClass() method to determine if an object is a string or Test, if it is a string, I hide the test's RelativeLayout, if it is a test then I hide the RelativeLayout of the subject. But when scrolling, items get removed and and re-added randomly.
my adapter's class:
public class MarksAdapter extends RecyclerView.Adapter<MarksAdapter.MyHolder>{
public class MyHolder extends RecyclerView.ViewHolder{
RelativeLayout card;
TextView title;
TextView total;
View divider;
int posito;
RelativeLayout group;
TextView groupTitle;
TextView groupMark;
public MyHolder(View itemView) {
super(itemView);
this.card = (RelativeLayout)itemView.findViewById(R.id.card);
this.title = (TextView)itemView.findViewById(R.id.title);
this.total = (TextView)itemView.findViewById(R.id.mark);
this.divider = itemView.findViewById(R.id.item_divider);
this.group = (RelativeLayout)itemView.findViewById(R.id.group);
this.groupTitle = (TextView)itemView.findViewById(R.id.group_title);
this.groupMark = (TextView)itemView.findViewById(R.id.group_mark);
}
}
final ArrayList marks;
Context ctx;
String selectedSem;
TestDatabase db;
public MarksAdapter(Context c, ArrayList marks,String sem,TestDatabase db,ArrayList<Integer> sections){
this.marks = marks;
ctx = c;
selectedSem = sem;
this.db = db;
}
#Override
public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new MyHolder(LayoutInflater.from(ctx).inflate(R.layout.mark_child, parent, false));
}
int lastPosition = -1;
int offset = 0;
#Override
public void onBindViewHolder(final MyHolder holder, final int positioner) {
holder.posito = positioner;
if(marks.get(holder.posito).getClass() == Test.class) {
holder.group.setVisibility(View.GONE);
//mark
final Test test = (Test)marks.get(positioner);
holder.title.setText(test.getName());
holder.total.setText(String.format(ctx.getString(R.string.new_m_sum), test.getMarkGot(), test.getMarkOver()));
//add here
holder.card.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(ctx,addTest.class);
Test mark = (Test)marks.get(holder.posito);
i.putExtra("t_name",mark.getName());
i.putExtra("subject",mark.getSubject());
i.putExtra("mark_got",mark.getMarkGot());
i.putExtra("mark_over",mark.getMarkOver());
i.putExtra("mode","edit");
i.putExtra("oldId", mark.getId());
ctx.startActivity(i);
}
});
holder.card.setLongClickable(true);
holder.card.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(final View v) {
final Dialog dialo = new Dialog(ctx);
dialo.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialo.setContentView(R.layout.material_dialog);
TextView title = (TextView) dialo.findViewById(R.id.title);
TextView body = (TextView) dialo.findViewById(R.id.body);
Button negative = (Button) dialo.findViewById(R.id.negative);
negative.setText(ctx.getString(R.string.cancel));
Button positive = (Button) dialo.findViewById(R.id.positive);
positive.setText(ctx.getString(R.string.Delete));
title.setText(ctx.getString(R.string.d));
body.setText(ctx.getString(R.string.q_delete) + " " + test.getName() + " " + ctx.getString(R.string.de_comp));
negative.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialo.dismiss();
}
});
positive.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View vir) {
TestDatabase tb = new TestDatabase(ctx);
SemesterDatabase semesterDatabase = new SemesterDatabase(ctx);
tb.deleteTest(holder.posito, semesterDatabase.getSelected().getName());
MarksAdapter.this.notifyItemRemoved(holder.posito);
marks.remove(holder.posito);
for (int i = 0; i < marks.size(); i++) {
if(!(marks.get(i) instanceof Test)) {
String sub = String.valueOf(marks.get(i));
if(db.isNoValue(sub,selectedSem)){
marks.remove(i);
notifyItemRemoved(i);
}
}
}
dialo.dismiss();
}
});
dialo.show();
return true;
}
});
}else {
holder.group.setVisibility(View.VISIBLE);
holder.card.setVisibility(View.GONE);
//group
if(holder.posito == 0) {
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)holder.group.getLayoutParams();
params.setMargins(0,0,0,0);
holder.group.setLayoutParams(params);
}
String sub = String.valueOf(marks.get(holder.posito));
holder.groupTitle.setText(sub);
holder.groupMark.setText(db.getTotalSubjectMarks(sub,selectedSem));
}
if(lastPosition < holder.posito) {
if(holder.card.getVisibility() == View.VISIBLE) {
Animation slide = AnimationUtils.loadAnimation(ctx, R.anim.marks);
slide.setInterpolator(new AccelerateInterpolator());
slide.setDuration(700);
offset += 100;
slide.setStartOffset(offset);
holder.card.startAnimation(slide);
} else {
Animation slide = AnimationUtils.loadAnimation(ctx, R.anim.mark_groups);
slide.setInterpolator(new AccelerateInterpolator());
slide.setDuration(700);
offset += 50;
slide.setStartOffset(offset);
holder.group.startAnimation(slide);
}
lastPosition = holder.posito;
}
}
#Override
public int getItemCount() {
return marks.size();
}
}
Note: I already tried the itemViewType method but it didn't work for me
Thanks in advance!
I believe you missed to set holder.card back to visible, like this
if(marks.get(holder.posito).getClass() == Test.class) {
holder.card.setVisibility(View.Visible); //add back this
holder.group.setVisibility(View.GONE);

how to maintain inflated radio button state in listView

So I have a listView that I'm populating with a static xml, but inside that xml I have a dynamic container that I inflate items into when the user clicks on an item in the listView.
Basically the view(s) I'm inflating looks like (x) amount of radio buttons and a textView.
The reason I have to do it this way is that the amount of radio buttons inflated could change depending on what type of list item it is.
The issue I'm running into is that once the radio buttons are inflated and the user selects a button, the list doesn't save the state from which the user last selected the radio button. Or rather, it recycles the radio button state to another position in the list. Which is somewhat correct since that's what listview does. I want it to only save the user selected answer at the position they selected in the listView.
I've been working on this for about a week and can't find a good solution. If anyone would like to help I'd greatly appreciate it. I'll post the relevant code below.
SurveyView (Custom container to inflate views into)
public class SurveyView extends LinearLayout {
private LinearLayout pollContainer;
private Context context;
private String type;
private int numOfAnswers;
private ListView answersList;
private ArrayList<String> answers;
private boolean visibility = true;
private OnClickListener listener;
private ArrayList<View> options;
private static int tag = 88888888;
private ArrayList<Boolean> checked;
private Integer[] percent = {33, 25, 15, 20, 7};
private int position;
/**
* #param context the context of the activity
* #param type the type of poll
* #param numOfAnswers if the poll is multiple choice (most likely) provide number of answers.
*/
public void setLayout(final Context context, String type, int numOfAnswers, final int position) {
this.type = type;
this.numOfAnswers = numOfAnswers;
this.context = context;
this.position = position;
switch (type) {
case "Multiple":
if (visibility) {
for (int i = 0; i < numOfAnswers; i++) {
View v = LayoutInflater.from(getContext()).inflate(R.layout.poll_multiple_choice_answers_row, null);
View space = LayoutInflater.from(getContext()).inflate(R.layout.space, null);
v.setTag(tag);
options.add(v);
final RadioButton rb = (RadioButton) v.findViewById(R.id.answer_voted_button);
rb.setClickable(false);
rb.setFocusable(false);
tag++;
addView(v);
addView(space);
}
}
break;
case "Slider":
break;
case "Tree":
break;
case "Sentiment":
break;
}
}
public SurveyView(Context context, AttributeSet attrs) {
super(context, attrs);
setOrientation(VERTICAL);
options = new ArrayList<>();
}
public boolean isVisibility() {
return visibility;
}
public void setVisibility(boolean visibility) {
this.visibility = visibility;
}
public void setAnswers(int position) {
RadioButton rb;
for (int i = 0; i < options.size(); i++) {
if (i != position) {
rb = (RadioButton) options.get(i).findViewById(R.id.answer_voted_button);
rb.setChecked(false);
}
else {
rb = (RadioButton) options.get(position).findViewById(R.id.answer_voted_button);
rb.setChecked(true);
for (int p = 0; p < options.size(); p++) {
TextView answer = (TextView) options.get(p).findViewById(R.id.poll_answer);
answer.setText("Abraham Lincoln");
TextView tv = (TextView) options.get(p).findViewById(R.id.answer_percent);
tv.setText(Integer.toString(percent[p]));
options.get(p).setBackground(new PercentDrawable(percent[p], context.getResources().getColor(R.color.icitizen_poll_opaque_gold)));
}
}
}
}
Adapter for the listview
PollsAdapter extends BaseAdapter {
private LayoutInflater inflater;
private Context context;
private ArrayList<Card> data;
private ArrayList<RelativeLayout.LayoutParams> params;
private ArrayList<Integer> pollAnswers;
private int selectedPosition = 0;
public PollsAdapter(Context context, ArrayList<Card> data,
ArrayList<RelativeLayout.LayoutParams> params,
ArrayList<Integer> pollAnswers) {
this.context = context;
this.data = data;
inflater = LayoutInflater.from(context);
this.params = params;
this.pollAnswers = pollAnswers;
}
public static class ViewHolder {
TextView type;
TextView time;
TextView text;
TextView space;
TextView pollSpace;
ImageView type_icon;
SurveyView answerView;
RadioButton rb;
ArrayList<View> options;
private ViewHolder() {
}
private ViewHolder(TextView type, TextView time, TextView text, ImageView type_icon, SurveyView answerView) {
this.type = type;
this.time = time;
this.text = text;
this.type_icon = type_icon;
this.answerView = answerView;
}
public TextView getType() {
return type;
}
public void setType(TextView type) {
this.type = type;
}
public TextView getTime() {
return time;
}
public void setTime(TextView time) {
this.time = time;
}
public TextView getText() {
return text;
}
public void setText(TextView text) {
this.text = text;
}
public ImageView getType_icon() {
return type_icon;
}
public void setType_icon(ImageView type_icon) {
this.type_icon = type_icon;
}
public SurveyView getAnswerView() {
return answerView;
}
public void setAnswerView(SurveyView answerView) {
this.answerView = answerView;
}
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = inflater.inflate(R.layout.polls_card_layout, null);
viewHolder.type = (TextView)convertView.findViewById(R.id.card_type);
viewHolder.time = (TextView)convertView.findViewById(R.id.card_poll_time);
viewHolder.text = (TextView)convertView.findViewById(R.id.card_text);
viewHolder.space = (TextView)convertView.findViewById(R.id.card_space);
viewHolder.pollSpace = (TextView)convertView.findViewById(R.id.poll_space);
viewHolder.type_icon = (ImageView)convertView.findViewById(R.id.card_icon);
viewHolder.answerView = (SurveyView)convertView.findViewById(R.id.poll_component);
viewHolder.rb = (RadioButton)viewHolder.answerView.findViewById(R.id.answer_voted_button);
convertView.setTag(viewHolder);
}
else {
viewHolder = (ViewHolder)convertView.getTag();
}
viewHolder.type.setText(data.get(position).getType());
viewHolder.time.setText(data.get(position).getTime());
viewHolder.text.setText(data.get(position).getText());
viewHolder.answerView.setLayoutParams(params.get(position));
viewHolder.answerView.setLayout(context, "Multiple", 5, position);
viewHolder.answerView.setVisibility(false);
viewHolder.answerView.setAnswers(pollAnswers.get(position));
return convertView;
}
The fragment for the listview
SurveyListFragment extends ListFragment {
private ArrayList<Card> cardList;
private PollsAdapter adapter;
private ArrayList<Answer> answers;
ArrayList<Integer> visible;
private ArrayList<RelativeLayout.LayoutParams> params;
private ArrayList<Integer> pollAnswers;
/**
when user clicks on a poll display the poll options for it
*/
#Override
public void onListItemClick(ListView l, View view, final int position, long id) {
final PollsAdapter.ViewHolder holder = (PollsAdapter.ViewHolder)adapter.getView(position, view, l).getTag();
if (holder.getAnswerView().getHeight() == 0) {
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.BELOW, R.id.poll_space);
params.addRule(RelativeLayout.RIGHT_OF, R.id.card_icon);
//holder.getAnswerView().setLayoutParams(params);
this.params.set(position, params);
for (int i = 0; i < holder.getAnswerView().getOptions().size(); i++) {
holder.getAnswerView().getOptions().get(i).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for (int p = 0; p < holder.getAnswerView().getOptions().size(); p++) {
if (holder.getAnswerView().getOptions().get(p) == v) {
holder.getAnswerView().setAnswers(p);
pollAnswers.set(position, p);
adapter = new PollsAdapter(getActivity(), cardList, SurveyListFragment.this.params, pollAnswers);
setListAdapter(adapter);
}
}
}
});
}
}
else {
holder.getAnswerView().setVisibility(false);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, 0);
params.addRule(RelativeLayout.BELOW, R.id.poll_space);
params.addRule(RelativeLayout.RIGHT_OF, R.id.card_icon);
this.params.set(position, params);
// holder.getAnswerView().setLayoutParams(params);
adapter.notifyDataSetChanged();
}
super.onListItemClick(l, view, position, id);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setListAdapter(adapter);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
cardList = new ArrayList<>();
answers = new ArrayList<>();
visible = new ArrayList<>();
params = new ArrayList<>();
pollAnswers = new ArrayList<>();
Answer answer = new Answer();
answer.setText("one");
answers.add(answer);
answer = new Answer();
answer.setText("two");
answers.add(answer);
answer = new Answer();
answer.setText("three");
answers.add(answer);
answer = new Answer();
answer.setText("four");
answers.add(answer);
Card card = new Card();
card.setType("Polls");
card.setText("What issue listed below would you like to see as a priority for Nashville’s next mayor?");
card.setTime("Closing Soon");
for (int i = 0; i < cardList.size(); i++) {
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, 0);
params.addRule(RelativeLayout.BELOW, R.id.poll_space);
params.addRule(RelativeLayout.RIGHT_OF, R.id.card_icon);
this.params.add(params);
pollAnswers.add(-1);
}
adapter = new PollsAdapter(getActivity(), cardList, params, pollAnswers);
}
Parse the survey object to the view class when you create the convertView. And parse a new object every time recycle previous views. Here are some codes.
1) Initialize the views in ProductListItemView
public ProductListItemView(Context context, ProductItem item) {
super(context);
mProductItem = item;
initView(context);
}
/**
* This function sets up all the Views contained in the FrameLayout
*
* #param context
*/
private void initView(Context context) {
addView(LayoutInflater.from(context).inflate(R.layout.list_item_product, null));
ButterKnife.inject(this);
if (mProductItem != null) {
setProductItem(mProductItem);
}
}
2) set object to the view
public void setProductItem(final ProductItem item) {
/**
* Clear Listener. Important!! Cause by Android Recycle View
* Do whatever you want to reset the recycled view or new view
*/
mPurchase.setOnClickListener(null);
endorsed_by_image.setVisibility(INVISIBLE);
endorsed_by_name.setVisibility(INVISIBLE);
mBtnEndorse.setOnCheckedChangeListener(null);
mProductItem = item;
mProductName.setText(mProductItem.getName());
3) In your adapter
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ProductItem item = mProducts.get(position);
if (convertView == null) {
convertView = new ProductListItemView(getActivity(), item);
} else {
((ProductListItemView) convertView).setProductItem(item);
}
}
Hope I explain it well.
And in getView(), it is better to implement ViewHolder. Visit http://www.javacodegeeks.com/2013/09/android-viewholder-pattern-example.html

Categories

Resources