java custom - ListView personnalisé Android impossible de cliquer sur des éléments





adapter studio (5)


J'ai rencontré un problème similaire et j'ai trouvé que le CheckBox est assez compliqué dans un ListView. Ce qui se passe est qu'il impose sa volonté sur l'ensemble ListItem, et sorte de surcharger le onListItemClick. Vous souhaiterez peut-être implémenter un gestionnaire de clic pour cela et définir la propriété de texte pour le contrôle CheckBox, au lieu d'utiliser les TextViews.

Je dirais que regarder dans cet objet View, il peut fonctionner mieux que le CheckBox

Affichage du texte coché

J'ai donc un objet ListView personnalisé. Les éléments de la liste ont deux textures empilées les unes sur les autres, plus une barre de progression horizontale que je veux garder cachée jusqu'à ce que je fasse quelque chose. À l'extrême droite se trouve une case à cocher que je ne veux afficher que lorsque l'utilisateur doit télécharger des mises à jour de ses bases de données. Lorsque je désactive la case en définissant la visibilité de Visibility.GONE, je suis en mesure de cliquer sur les éléments de la liste. Lorsque la case à cocher est visible, je ne peux pas cliquer sur quelque chose dans la liste à l'exception des cases à cocher. J'ai fait quelques recherches mais n'ai rien trouvé de pertinent dans ma situation actuelle. J'ai trouvé cette question mais j'utilise un ArrayAdapter surchargé puisque j'utilise ArrayLists pour contenir la liste des bases de données en interne. Est-ce que je dois juste obtenir la vue LinearLayout et ajouter un onClickListener comme Tom l'a fait? Je ne suis pas sûr.

Voici le XML de la disposition des lignes listview:

<?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 le ListActivity. Évidemment, il est encore en développement, donc pardonnez les choses qui manquent ou qui pourraient être laissées traîner:

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: J'ai toujours ce problème. Je triche et j'ajoute des gestionnaires onClick aux textviews mais il semble extrêmement stupide que ma fonction onListItemClick () ne soit pas appelée du tout quand je ne clique pas sur ma case.




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

android: descendantFocusability = "blocsDescendants"




Le problème est qu'Android ne vous permet pas de sélectionner des éléments de liste qui contiennent des éléments qui peuvent être mis en surbrillance. J'ai modifié la case à cocher de l'élément de liste pour avoir un attribut comme ceci:

android:focusable="false"

Maintenant mes éléments de liste qui contiennent des cases à cocher (fonctionnent aussi pour les boutons) sont "sélectionnables" dans le sens traditionnel (ils s'allument, vous pouvez cliquer n'importe où dans la liste et le gestionnaire "onListItemClick" se déclenchera, etc).

EDIT: Comme une mise à jour, un commentateur a mentionné "Juste une note, après avoir changé la visibilité du bouton, j'ai dû désactiver le focus par programmation."




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

android:descendantFocusability="blocksDescendants"

Et l'indicateur ImageButton à true dans la vue ImageButton .

android:focusableInTouchMode="true"



savedInstanceState sert uniquement à enregistrer l'état associé à une instance actuelle d'une activité, par exemple les informations de navigation ou de sélection en cours, de sorte que si Android détruit et recrée une activité, elle peut revenir telle qu'elle était auparavant. Voir la documentation sur onCreate et onSaveInstanceState

Pour un état plus long, envisagez d'utiliser une base de données SQLite, un fichier ou des préférences. Voir Enregistrement d'un état persistant .





java android