0

I have this list view where you can select the items to buy. When you click on an item a group of elements appears. (The checkbox, the 2 buttons, and the textview.) Where you can select the quantity of the product that you want to buy.

This group of elements is hidden in the Layout. The visibility of this group of elements changes from VIEW.GONE to VIEW.VISIBLE

enter image description here

The problem is that the buttons appear randomly in other rows. For example, when I click on the THIN BEER the group of elements appears on the view, but when I scroll down the app, the group of elements also appear on the HAMBURGER row and other.

enter image description here

And when I change the value on one of the textview, also increase in the other elements.

enter image description here

enter image description here

   public class ProductAdapter extends ArrayAdapter<Product> {
        ArrayList<Boolean> positionArray;
        public ProductAdapter(Context context, ArrayList<Product> products){
            super(context,0,products);
            positionArray = new ArrayList<Boolean>(products.size());
            for(int i =0;i<products.size();i++){
                positionArray.add(false);
            }
        }

        public static class ViewHolder{
            TextView tv_price,tv_prodName, tv_details, tv_location;
            ImageView imgView_productImage;
            CheckBox checkBox;
            Button bntUp,btnDown;
        }
        //When a listview recycles views , it recycles its present state as well as listeners attached to it.if the checkbox was checked and has a
        // onCheckedChangeListener set, both will remain a part of recycled view based on position.
        // So it is our responsibility to reset all states and remove previous listeners.
        @NonNull
        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder;
            Product product = getItem(position);
            if(convertView==null){
                convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_product_item,parent, false);
                viewHolder = new ViewHolder();

                viewHolder.imgView_productImage = (ImageView)convertView.findViewById(R.id.list_item_imgView_productImage);
                viewHolder.tv_price = (TextView)convertView.findViewById(R.id.listItem_tv_price);
                viewHolder.tv_prodName = (TextView)convertView.findViewById(R.id.listItem_tv_productName);
                viewHolder.tv_location = (TextView)convertView.findViewById(R.id.listItem_tv_location);
                viewHolder.tv_details = (TextView)convertView.findViewById(R.id.listItem_tv_productDetail);
                viewHolder.checkBox = (CheckBox)convertView.findViewById(R.id.listProd_checkbox);
                viewHolder.bntUp = (Button)convertView.findViewById(R.id.listProd_up);
                viewHolder.btnDown = (Button)convertView.findViewById(R.id.listProd_down);

                convertView.setTag(viewHolder);



            }else{
                viewHolder = (ViewHolder)convertView.getTag();
                viewHolder.checkBox.setOnCheckedChangeListener(null); //
            }
            viewHolder.tv_price.setText("$" + String.valueOf(product.getPrice()));
            viewHolder.tv_prodName.setText(product.getProductName());
            viewHolder.tv_location.setText(product.getLocation());
            viewHolder.tv_details.setText(product.getProductDetail());
            viewHolder.imgView_productImage.setImageBitmap(MifareUtilities.getDecodeImage(product.getProductImage()));
            viewHolder.checkBox.setChecked(positionArray.get(position));
            viewHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    if(isChecked){
                        positionArray.set(position,true);
                    }else {
                        positionArray.set(position,false);
                    }
                }
            });

            return convertView;
        }


    `}

And this is the code that is on my Fragment, where I show up the listView

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    productsList = new HashMap<>();
    final View viewroot = inflater.inflate(R.layout.fragment_payment, container, false);
    final ArrayList<Product> products = (ArrayList<Product>)new ProductController(new ProductFromString()).getProducts();
    final ListView listView = (ListView)viewroot.findViewById(R.id.fragPayment_listview);
    ProductAdapter productAdapter = new ProductAdapter(getActivity(),products);
    listView.setAdapter(productAdapter);
    listView.setLongClickable(true);


    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, final int position, long id) {
            final int  positionf = position;
            final CheckBox checkBox = (CheckBox)view.findViewById(R.id.listProd_checkbox);
            checkBox.setVisibility(View.VISIBLE);
            checkBox.setChecked(!checkBox.isChecked());
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if(!checkBox.isChecked()){
                        productsList.remove(String.valueOf(position));
                    }else {
                        Product product = (Product) listView.getAdapter().getItem(positionf);
                        productsList.put(String.valueOf(position),product);
                    }
                }
            });
            final Button btnUp = (Button)view.findViewById(R.id.listProd_up);
            final Button btnDown = (Button)view.findViewById(R.id.listProd_down);
            final TextView quantity = (TextView)view.findViewById(R.id.listItem_quantity);
            btnUp.setTag(position);
            btnDown.setTag(position);
            btnDown.setVisibility(View.VISIBLE);
            btnUp.setVisibility(View.VISIBLE);
            quantity.setVisibility(View.VISIBLE);
            btnDown.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //String q = quantity.getText().toString();
                    int quan = Integer.parseInt(quantity.getText().toString());
                    //int btnPosition = (Integer)v.getTag();

                    if(quan!=1){
                        quan --;
                        quantity.setText(String.valueOf(quan));
                        updateProductQuantity(listView,(Integer)v.getTag(),Integer.parseInt(quantity.getText().toString()) );
                    }else { //if the quantity is 0 it will hide the buttons and uncheck
                        btnDown.setVisibility(View.GONE);
                        btnUp.setVisibility(View.GONE);
                        checkBox.setChecked(false);
                        quantity.setVisibility(View.GONE);
                        checkBox.setVisibility(View.GONE);
                        //remove product from list
                        productsList.remove(String.valueOf((Integer)v.getTag()));

                    }
                }
            });
            btnUp.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int quan = Integer.parseInt(quantity.getText().toString());
                    quan++;
                    quantity.setText(String.valueOf(quan));
                  //  updateProductQuantity(listView,(Integer)v.getTag(),Integer.parseInt(quantity.getText().toString()) );
                }
            });



        }
    });
    listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {

        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
            final Product product = (Product) listView.getAdapter().getItem(position);
            //dlgShowConfig(product);
            Intent intentActivityPayment = new Intent(getActivity(), ActivityPayment.class);
            intentActivityPayment.putExtra("productObject",product);
            startActivity(intentActivityPayment);
            return true; //evitara que se ejecute el onitemclicklistener cuando ejecutes el onitemlongclicklisstener
        }
    });


    return viewroot;
    }
mavi
  • 1,074
  • 2
  • 15
  • 29
  • where u handling visibility of group items? – Pavan May 26 '17 at 16:38
  • you have to handle it in adapter getview method u can maintain state using your adapter data – Pavan May 26 '17 at 16:46
  • Im handling the visibility in the Layout list_product_item.xml. Also in the fragment on the method onCreateView. – mavi May 26 '17 at 17:01
  • 1
    You have to handle on adapter too because after scroll views recycles so u have to maintain state on getview method – Pavan May 26 '17 at 17:03
  • In this question something similar was happening https://stackoverflow.com/questions/11190390/checking-a-checkbox-in-listview-makes-other-random-checkboxes-checked-too – mavi May 26 '17 at 17:04
  • 1
    Yes in that they handled using data and set the updated state on getview method – Pavan May 26 '17 at 17:05
  • But how to handle the visibility on the adapter if the listView exists on the Fragment? – mavi May 26 '17 at 17:11
  • When you want to show that extra views and at a time there will be one or multiple – Pavan May 26 '17 at 17:12
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/145225/discussion-between-mavi-and-pavan). – mavi May 26 '17 at 17:13

2 Answers2

1

If I understood you correctly whenever you create a new ListView item by scrolling it down all those buttons are shown in the item.

Logic suggests that what you need to do is hide the buttons again when the item is created, aka in your Adapter.

Ivan86
  • 356
  • 1
  • 14
0

You were right, the logic needs to be in the adapter and you need to save the state in a variable. I was already saving the state of my checkbox, to save the state I add a boolean variable in my product model.

Thanks @PAVAN for the help.

public class ProductAdapter extends ArrayAdapter<Product> {
ArrayList<Boolean> positionArray;
public ProductAdapter(Context context, ArrayList<Product> products){
    super(context,0,products);
    positionArray = new ArrayList<Boolean>(products.size());
    for(int i =0;i<products.size();i++){
        positionArray.add(false);
    }
}

public static class ViewHolder{
    TextView tv_price,tv_prodName, tv_details, tv_location, quantity;
    ImageView imgView_productImage;
    CheckBox checkBox;
    Button bntUp,btnDown;
}
//When a listview recycles views , it recycles its present state as well as listeners attached to it.if the checkbox was checked and has a
// onCheckedChangeListener set, both will remain a part of recycled view based on position.
// So it is our responsibility to reset all states and remove previous listeners.
@NonNull
@Override
public View getView(final int position, View convertView, ViewGroup parent) {

    final ViewHolder viewHolder;
    Product product = getItem(position);
    if(convertView==null){
        convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_product_item,parent, false);
        viewHolder = new ViewHolder();

        viewHolder.imgView_productImage = (ImageView)convertView.findViewById(R.id.list_item_imgView_productImage);
        viewHolder.tv_price = (TextView)convertView.findViewById(R.id.listItem_tv_price);
        viewHolder.tv_prodName = (TextView)convertView.findViewById(R.id.listItem_tv_productName);
        viewHolder.tv_location = (TextView)convertView.findViewById(R.id.listItem_tv_location);
        viewHolder.tv_details = (TextView)convertView.findViewById(R.id.listItem_tv_productDetail);
        viewHolder.checkBox = (CheckBox)convertView.findViewById(R.id.listProd_checkbox);
        viewHolder.bntUp = (Button)convertView.findViewById(R.id.listProd_up);
        viewHolder.btnDown = (Button)convertView.findViewById(R.id.listProd_down);
        viewHolder.quantity = (TextView)convertView.findViewById(R.id.listItem_quantity);

        convertView.setTag(viewHolder);



    }else{
        viewHolder = (ViewHolder)convertView.getTag();
        viewHolder.checkBox.setOnCheckedChangeListener(null); //
    }
    viewHolder.tv_price.setText("$" + String.valueOf(product.getPrice()));
    viewHolder.tv_prodName.setText(product.getProductName());
    viewHolder.tv_location.setText(product.getLocation());
    viewHolder.tv_details.setText(product.getProductDetail());
    viewHolder.imgView_productImage.setImageBitmap(MifareUtilities.getDecodeImage(product.getProductImage()));
    viewHolder.checkBox.setChecked(positionArray.get(position));
    int visible = positionArray.get(position) == true ? View.VISIBLE : View.GONE;
    viewHolder.checkBox.setVisibility(visible);
    viewHolder.bntUp.setVisibility(visible);
    viewHolder.btnDown.setVisibility(visible);
    viewHolder.quantity.setVisibility(visible);
    viewHolder.quantity.setText(String.valueOf(product.getQuantity()));
    viewHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            if(isChecked){
                positionArray.set(position,true);
                //show buttons
                changeVisibility(viewHolder,View.VISIBLE);
            }else {
                positionArray.set(position,false);
                changeVisibility(viewHolder,View.GONE);
            }
        }
    });

    return convertView;
}

public void changeVisibility(ViewHolder viewHolder, int visibility){
    viewHolder.bntUp.setVisibility(visibility);
    viewHolder.btnDown.setVisibility(visibility);
    viewHolder.quantity.setVisibility(visibility);
    viewHolder.checkBox.setVisibility(visibility);
}
}
mavi
  • 1,074
  • 2
  • 15
  • 29