web-dev-qa-db-fra.com

Case décochée lorsque je fais défiler la liste sur Android

Je suis nouveau sur Android. J'ai créé un listview avec un textbox et checkbox.

Lorsque je vérifie le checkbox et le fait défiler vers le bas pour vérifier certains autres éléments dans la liste, les plus anciens ne sont pas cochés.

Comment éviter ce problème dans un listview? Veuillez me guider avec mon code.

Voici le code:

main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:orientation="vertical"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent">

    <TextView
        Android:id="@+id/TextView01"
        Android:layout_height="wrap_content"
        Android:text="List of items"
        Android:textStyle="normal|bold"
        Android:gravity="center_vertical|center_horizontal"
        Android:layout_width="fill_parent"/>

    <ListView
        Android:id="@+id/ListView01"
        Android:layout_height="250px"
        Android:layout_width="fill_parent"/>

    <Button
        Android:text="Save"
        Android:id="@+id/btnSave"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"/>

</LinearLayout>

Voici la page XML que j'ai utilisée pour créer une ligne de liste dynamique:

listview.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_height="wrap_content"
    Android:gravity="left|center"
    Android:layout_width="wrap_content"
    Android:paddingBottom="5px"
    Android:paddingTop="5px"
    Android:paddingLeft="5px">

    <TextView
        Android:id="@+id/TextView01"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:gravity="center"
        Android:textColor="#FFFF00"
        Android:text="hi"/>

    <TextView
        Android:text="hello"
        Android:id="@+id/TextView02"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_marginLeft="10px"
        Android:textColor="#0099CC"/>

    <EditText
        Android:id="@+id/txtbox"
        Android:layout_width="120px"
        Android:layout_height="wrap_content"
        Android:textSize="12sp"
        Android:layout_x="211px"
        Android:layout_y="13px"/>

    <CheckBox
        Android:id="@+id/chkbox1"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"/>

</LinearLayout>

Ceci est ma classe d'activité.

CustomListViewActivity.Java:

public class CustomListViewActivity extends Activity {

    ListView lstView;
    static Context mContext;
    Button btnSave;

    private static class EfficientAdapter extends BaseAdapter {
        private LayoutInflater mInflater;

        public EfficientAdapter(Context context) {
            mInflater = LayoutInflater.from(context);

        }

        public int getCount() {
            return country.length;
        }

        public Object getItem(int position) {
            return position;
        }

        public long getItemId(int position) {
            return position;
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            final ViewHolder holder;
            if (convertView == null) {
                convertView = mInflater.inflate(R.layout.listview, parent,
                        false);
                holder = new ViewHolder();
                holder.text = (TextView) convertView
                        .findViewById(R.id.TextView01);
                holder.text2 = (TextView) convertView
                        .findViewById(R.id.TextView02);
                holder.txt = (EditText) convertView.findViewById(R.id.txtbox);
                holder.cbox = (CheckBox) convertView.findViewById(R.id.chkbox1);

                convertView.setTag(holder);
            }
            else {
                holder = (ViewHolder) convertView.getTag();
            }

            holder.text.setText(curr[position]);
            holder.text2.setText(country[position]);
            holder.txt.setText("");
            holder.cbox.setChecked(false);

            return convertView;
        }

        public class ViewHolder {
            TextView text;
            TextView text2;
            EditText txt;
            CheckBox cbox;
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        lstView = (ListView) findViewById(R.id.ListView01);
        lstView.setAdapter(new EfficientAdapter(this));
        btnSave = (Button)findViewById(R.id.btnSave);
        mContext = this;

        btnSave.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // I want to print the text which is in the listview one by one.
                // Later I will insert it in the database.
                //
                //            Toast.makeText(getBaseContext(), "EditText Value, checkbox value and other values", Toast.LENGTH_SHORT).show();
                for (int i = 0; i < lstView.getCount(); i++) {
                    View listOrderView;
                    listOrderView = lstView.getChildAt(i);
                    try{
                        EditText txtAmt = (EditText)listOrderView.findViewById(R.id.txtbox);
                        CheckBox cbValue = (CheckBox)listOrderView.findViewById(R.id.chkbox1);
                        if(cbValue.isChecked()== true){
                            String amt = txtAmt.getText().toString();
                            Toast.makeText(getBaseContext(), "Amount is :"+amt, Toast.LENGTH_SHORT).show();
                        }

                    }
                    catch (Exception e) {
                        // TODO: handle exception
                    }
                }

            }
        });
    }

    private static final String[] country = { "item1", "item2", "item3",
        "item4", "item5", "item6","item7", "item8", "item9",
        "item10", "item11", "item12" };

    private static final String[] curr = { "1", "2", "3", "4", "5", "6","7", "8", "9", "10", "11", "12" };
}

Veuillez m'aider à résoudre ce problème.

J'ai évoqué ce problème à de nombreux endroits. Mais je n'ai pas pu obtenir de réponse appropriée pour résoudre ce problème.

Veuillez me fournir le code pour éviter de décocher la case lorsque vous faites défiler vers le haut ou vers le bas.

29
Mathew

Dans l'appel de l'adaptateur listview personnalisé setChecked après appel setOnCheckedChangeListener.

De cette façon, vous séparez le lien vers l'ancien écouteur de la vue recyclée.

34
varotariya vajsi

Vous pouvez utiliser le code d'adaptateur suivant pour exécuter parfaitement une case à cocher dans un ListView.

Une démo détaillée est ici: Listview With Checkbox Android

Voir le lien de démonstration détaillé pour des informations détaillées. Il montre également comment envoyer des informations vérifiées à l'activité suivante.

import Android.content.Context;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;
import Android.widget.BaseAdapter;
import Android.widget.CheckBox;
import Android.widget.TextView;
import Android.widget.Toast;
import Java.util.ArrayList;


public class CustomAdapter  extends BaseAdapter {

    private Context context;
    public static ArrayList<Model> modelArrayList;

    public CustomAdapter(Context context, ArrayList<Model> modelArrayList) {

        this.context = context;
        this.modelArrayList = modelArrayList;
    }

    @Override
    public int getViewTypeCount() {
        return getCount();
    }

    @Override
    public int getItemViewType(int position) {
        return position;
    }

    @Override
    public int getCount() {
        return modelArrayList.size();
    }

    @Override
    public Object getItem(int position) {
        return modelArrayList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final ViewHolder holder;

        if (convertView == null) {
            holder = new ViewHolder(); LayoutInflater inflater = (LayoutInflater) context
                     .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.lv_item, null, true);

            holder.checkBox = (CheckBox) convertView.findViewById(R.id.cb);
            holder.tvAnimal = (TextView) convertView.findViewById(R.id.animal);

            convertView.setTag(holder);
        }
        else {
            // The getTag returns the viewHolder object set as a tag to the view
            holder = (ViewHolder)convertView.getTag();
        }

        holder.checkBox.setText("Checkbox " + position);
        holder.tvAnimal.setText(modelArrayList.get(position).getAnimal());

        holder.checkBox.setChecked(modelArrayList.get(position).getSelected());

        holder.checkBox.setTag(R.integer.btnplusview, convertView);
        holder.checkBox.setTag( position);
        holder.checkBox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                View tempview = (View) holder.checkBox.getTag(R.integer.btnplusview);
                TextView tv = (TextView) tempview.findViewById(R.id.animal);
                Integer pos = (Integer)  holder.checkBox.getTag();
                Toast.makeText(context, "Checkbox " + pos + " clicked!", Toast.LENGTH_SHORT).show();

                if (modelArrayList.get(pos).getSelected()){
                    modelArrayList.get(pos).setSelected(false);
                }
                else {
                    modelArrayList.get(pos).setSelected(true);
                }

            }
        });

        return convertView;
    }

    private class ViewHolder {

        protected CheckBox checkBox;
        private TextView tvAnimal;
    }
}

Model est

public class Model {

    private boolean isSelected;

    private String animal;

    public String getAnimal() {
        return animal;
    }

    public void setAnimal(String animal) {
        this.animal = animal;
    }

    public boolean getSelected() {
        return isSelected;
    }

    public void setSelected(boolean selected) {
        isSelected = selected;
    }
}
5
user6017633

Dans votre getView() vous avez la ligne suivante

holder.cbox.setChecked(false);

qui désactive CheckBox à chaque appel de getView() (lorsque vous faites défiler votre liste, par exemple)

3
Vladimir

Blockquote

** Dans la méthode getView () latérale, il suffit d'appeler comme ceci >>

check.setOnCheckedChangeListener(new OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(CompoundButton arg0, boolean arg1) 
            {

                if(check.isChecked())
                {
                    //checked
                    chkArray[position]=true;
                }
                else
                {   //uncheck
                  chkArray[position]=false;

                }
            }
        });

//check condition for checkboxes
        if(chkArray.length>0)
        {
            for (int i = 0; i < chkArray.length; i++) 
            {
                if(chkArray[position]!=null && chkArray[position])
                {
                    check.setChecked(true);
                }
            }
        }
1
ranjan

enfin je suis arrivé à la solution quelques heures plus tard, c'est par

  1. ajoutez une classe de tableau de variables booléennes avec les méthodes set et get.
  2. ajouter un tableau pour y enregistrer mes sélections.
  3. utilisez onClickListner.

à l'intérieur de la méthode getView comme suit:


if(marray!=null) { //if myarray class object has data
holder.name.setText(marray.getName());
.
.
holder.checkbox.setChecked(marray.isChecked());//get the checkbox state 
}

donnez la valeur à la variable booléenne dans la méthode holder.checkbox.setOnClickListener comme:


holder.checkbox.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (allReport.UserSelection.contains(
Integer.parseInt(marrays.get(position)
.getIdd()))) // check if id selected before
                    {
      marray.setChecked(false);// marray is the object from myArray class
      allReport.UserSelection.remove(new Integer(Integer.parseInt(marrays.get(position).getIdd())));//remove id 


 }else{
       allReport.UserSelection.add(Integer.parseInt
           (marrays.get(position).getIdd()));//save the selection 
            marray.setChecked(true);//save the boolean to true}

c'est résoudre le problème pour moi j'espère que cela fait toute aide

0
Aly Abdelaal

J'ai également eu ce problème avant. Android fait cela pour économiser de l'espace; seuls les éléments que vous voyez actuellement sont chargés, et c'est ce que j'ai découvert.

Si vous êtes en bas de votre liste, l'ID 1 est peut-être en position 5. J'ai cherché sur le Web et je l'ai déjà découvert.

Mais ceci vous aidera: D

0
Boe-Dev

Considérer:

holder.cbox.setChecked(false);

Supprimez cette ligne. Lorsque vous faites défiler la vue de liste à chaque fois, la méthode getView () est appelée.

0
Bhargav Panchal