112 votes

Android ListView personnalisé ne peut pas cliquer sur les éléments

J'ai donc personnalisé ListView objet. Les éléments de la liste ont deux textviews empilés les uns sur les autres, plus horizontale de la barre de progression que je veux rester caché jusqu'à ce que j'ai réellement faire quelque chose. À l'extrême droite est une case à cocher que je ne veux afficher lorsque l'utilisateur doit télécharger les mises à jour de leur base de données(s). Quand j'ai désactiver la case à cocher par la définition de la visibilité à la Visibilité.ALLÉ, je suis en mesure de cliquer sur les éléments de la liste. Lorsque la case n'est visible, je ne suis pas en mesure de cliquer sur quoi que ce soit dans la liste, à l'exception des cases à cocher. J'ai fait quelques recherches mais je n'ai pas trouvé quelque chose de pertinent à ma situation actuelle. J'ai trouvé cette question mais je suis en utilisant un substituée ArrayAdapter depuis que je suis en utilisant ArrayLists pour contenir la liste des bases de données en interne. Dois-je tout simplement besoin d'obtenir le LinearLayout de visualiser et d'ajouter un onClickListener comme Tom l'a fait? Je ne suis pas sûr.

Voici la liste de la ligne de mise en page XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:padding="6dip">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="0dip"
        android:layout_weight="1"
        android:layout_height="fill_parent">
        <TextView
            android:id="@+id/UpdateNameText"
            android:layout_width="wrap_content"
            android:layout_height="0dip"
            android:layout_weight="1"
            android:textSize="18sp"
            android:gravity="center_vertical"
            />
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="0dip"
            android:layout_weight="1"
            android:id="@+id/UpdateStatusText"
            android:singleLine="true"
            android:ellipsize="marquee"
            />
        <ProgressBar android:id="@+id/UpdateProgress" 
                     android:layout_width="fill_parent" 
                     android:layout_height="wrap_content"
                     android:indeterminateOnly="false" 
                     android:progressDrawable="@android:drawable/progress_horizontal" 
                     android:indeterminateDrawable="@android:drawable/progress_indeterminate_horizontal" 
                     android:minHeight="10dip" 
                     android:maxHeight="10dip"                    
                     />
    </LinearLayout>
    <CheckBox android:text="" 
              android:id="@+id/UpdateCheckBox" 
              android:layout_width="wrap_content" 
              android:layout_height="wrap_content" 
              />
</LinearLayout>

Et voici la classe qui étend la ListActivity. Bien évidemment, il est toujours en développement donc pardonner les choses qui manquent ou qui sont peut-être laissé autour de la pose:

public class UpdateActivity extends ListActivity {

    AccountManager lookupDb;
    boolean allSelected;
    UpdateListAdapter list;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        lookupDb = new AccountManager(this);
        lookupDb.loadUpdates();

        setContentView(R.layout.update);
        allSelected = false;

        list = new UpdateListAdapter(this, R.layout.update_row, lookupDb.getUpdateItems());
        setListAdapter(list);

        Button btnEnterRegCode = (Button)findViewById(R.id.btnUpdateRegister);
        btnEnterRegCode.setVisibility(View.GONE);

        Button btnSelectAll = (Button)findViewById(R.id.btnSelectAll);
        btnSelectAll.setOnClickListener(new Button.OnClickListener() {
            @Override
            public void onClick(View v) {
                allSelected = !allSelected;

                for(int i=0; i < lookupDb.getUpdateItems().size(); i++) {
                    lookupDb.getUpdateItem(i).setSelected(!lookupDb.getUpdateItem(i).isSelected());
                }

                list.notifyDataSetChanged();
                // loop through each UpdateItem and set the selected attribute to the inverse 

            } // end onClick
        }); // end setOnClickListener

        Button btnUpdate = (Button)findViewById(R.id.btnUpdate);
        btnUpdate.setOnClickListener(new Button.OnClickListener() {
            @Override
            public void onClick(View v) {
            } // end onClick
        }); // end setOnClickListener

        lookupDb.close();
    } // end onCreate


    @Override
    protected void onDestroy() {
        super.onDestroy();

        for (UpdateItem item : lookupDb.getUpdateItems()) {
            item.getDatabase().close();        
        }
    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);

        UpdateItem item = lookupDb.getUpdateItem(position);

        if (item != null) {
            item.setSelected(!item.isSelected());
            list.notifyDataSetChanged();
        }
    }

    private class UpdateListAdapter extends ArrayAdapter<UpdateItem> {
        private List<UpdateItem> items;

        public UpdateListAdapter(Context context, int textViewResourceId, List<UpdateItem> items) {
            super(context, textViewResourceId, items);
            this.items = items;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View row = null;

            if (convertView == null) {
                LayoutInflater li = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                row = li.inflate(R.layout.update_row, null);
            } else {
                row = convertView;
            }

            UpdateItem item = items.get(position);

            if (item != null) {
                TextView upper = (TextView)row.findViewById(R.id.UpdateNameText);
                TextView lower = (TextView)row.findViewById(R.id.UpdateStatusText);
                CheckBox cb = (CheckBox)row.findViewById(R.id.UpdateCheckBox);

                upper.setText(item.getName());
                lower.setText(item.getStatusText());

                if (item.getStatusCode() == UpdateItem.UP_TO_DATE) {
                    cb.setVisibility(View.GONE);
                } else {
                    cb.setVisibility(View.VISIBLE);
                    cb.setChecked(item.isSelected());
                }

                ProgressBar pb = (ProgressBar)row.findViewById(R.id.UpdateProgress);
                pb.setVisibility(View.GONE);
            }
            return row;
        }

    } // end inner class UpdateListAdapter
}

edit: je suis toujours à avoir ce problème. Je suis de la tricherie et de l'ajout d'onClick les maîtres de la textviews mais il semble extrêmement stupide que mon onListItemClick() la fonction n'est pas appelée à tous, quand je ne suis pas en cliquant sur ma case.

244voto

MattC Points 8392

Le problème est que Android ne vous permet pas de sélectionner les éléments de la liste qui ont des éléments qui peut recevoir le focus. J'ai modifié la case à cocher sur l'élément de la liste à avoir un attribut de la sorte:

android:focusable="false"

Maintenant, ma éléments de la liste qui contient des cases à cocher (pour les boutons) sont "sélectionnable" dans le sens traditionnel du terme (ils s'allument, vous pouvez cliquer n'importe où dans l'élément de la liste et le "onListItemClick" gestionnaire d'incendie, etc).

EDIT: une mise à jour, un intervenant a mentionné, "Juste une remarque, après la modification de la visibilité du bouton j'ai eu par programmation désactiver le focus."

44voto

micyunu Points 673

Si vous avez ImageButton dans l'élément de liste, vous devez définir la valeur descendantFocusability sur "blocksDescendants" dans l'élément d'élément de liste racine.

 android:descendantFocusability="blocksDescendants"
 

Et le drapeau focusableInTouchMode à true dans la vue ImageButton .

 android:focusableInTouchMode="true"
 

13voto

Andrew Burgess Points 3053

J'ai eu un problème similaire se produire et a constaté que la Case à cocher est plutôt capricieux dans une ListView. Ce qui se passe est qu'il impose sur l'ensemble de la ListItem, et une sorte de remplace la onListItemClick. Vous pouvez implémenter un gestionnaire d'événements click pour cela, définissez la propriété text de la Case ainsi, au lieu d'utiliser le TextViews.

Je dirais de regarder dans ce point de Vue de l'objet ainsi, il peut fonctionner mieux que la Case à cocher

Vérifié L'Affichage Du Texte

10voto

Sarry Points 31

utiliser cette ligne dans la vue racine de l'élément de liste

android: descendantFocusability = "blocksDescendants"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X