Question

Je suis en train de recréer ce que Google a fait avec le ListView dans l'application Gmail. Je voudrais avoir en particulier, chaque élément de la liste comprennent un CheckBox et deux TextViews (l'une sur l'autre). J'ai besoin pour les auditeurs lorsque la case est cochée (ou cliqué) et quand partout ailleurs sur l'élément de liste est cliqué. Enfin, je voudrais ActionBar pour refléter le fait que les éléments sont sélectionnés et fournir des options comme Sélectionner tout, sélectionnez Aucun, etc (voir cette capture d'écran ).

entrer image description ici

Jusqu'à présent, voici la mise en page, je suis venu avec.

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

    <CheckBox android:id="@+id/checkBox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical|center_horizontal" />

    <LinearLayout android:id="@+id/linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="6dp"
        android:focusable="true"
        android:clickable="true" >

        <TextView android:id="@+id/titleTextView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="16sp" />

        <TextView android:id="@+id/dateTextView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="12sp" />

    </LinearLayout>

</LinearLayout>

affiche tout correctement, mais j'ai besoin des pointeurs sur la façon de mettre en place les auditeurs pour les deux vues ( @ + id / checkBox et @ + id / linearLayout1 ) . Je l'ai regardé List16 API démo , mais ils utilisent la mise en page simple_list_item_activated_1 et je ne suis pas sûr de ce que le XML pour qui ressemble. Comme leur code l'indique, j'ai créé un ModeCallback classe qui implémente ListView.MultiChoiceModeListener et je mets le mode de choix du ListView à CHOICE_MODE_MULTIPLE_MODAL, mais je ne sais pas comment obtenir le CheckBox dans ma mise en page au travail avec cela.

Quelqu'un at-il copié avec succès le comportement ListView de l'application Gmail? J'ai cherché un peu et ne pouvait pas arriver à quoi que ce soit (en dépit de plusieurs autres de poser des questions similaires, comme celui-ci - la plupart des réponses indiquent simplement revenir à cette même démo API)

.

En outre, pour le contexte, je suis le chargement de données à partir d'une base de données SQLite dans la liste et je l'ai créé mon propre adaptateur curseur (qui fonctionne très bien). Je sens que je dois mettre en place des méthodes d'auditeurs de cette classe dans le NewView () et Bindview (), mais tout ce que j'ai essayé n'a pas fonctionné.

Toutes les idées?

Était-ce utile?

La solution

Le mode dans la figure est appelé mode d'action. Si vous utilisez l'affichage de votre ligne personnalisée et adaptateur personnalisé, vous ne devez pas utiliser CHOICE_MODE_MULTIPLE_MODAL pour démarrer le mode d'action. Je l'ai essayé une fois échoué, et je soupçonne qu'il est utilisé pour adaptateur intégré.

Pour appeler le mode d'action par vous-même dans votre code, méthode d'appel startActionMode dans toute méthode d'écoute d'une de votre point de vue, que ce soit case à cocher, textview ou quelque chose comme ça. Vous passez ensuite la ModeCallback en tant que paramètres dans, et faire tout ce que l'opération que vous voulez faire en classe ModeCallback.

Je ne pense pas que celui-ci fonctionnerait sur Android 3.0 avant que.

Voici un bref exemple. J'ai une activité de liste extensible et je voudrais appeler le menu du mode d'action lors de l'enregistrement de l'utilisateur / décocher la case à cocher, et voici ma méthode de getChildView dans ma classe d'adaptateur personnalisé:

public View getChildView(int groupPosition, int childPosition,
            boolean isLastChild, View convertView, ViewGroup parent) {

        if (convertView == null) {
            LayoutInflater inflater =  (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.childrow, null);
        }
        CheckBox cb = (CheckBox)convertView.findViewById(R.id.row_check);
        cb.setChecked(false);   // Initialize
        cb.setTag(groupPosition + "," + childPosition);
        cb.setFocusable(false); // To make the whole row selectable
        cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                String tag = (String)buttonView.getTag();
                String[] pos = tag.split(",");
                if (isChecked) {
                    if (mActionMode == null) mActionMode = startActionMode(mMultipleCallback);                      
                }
                else {
                    if (mActionMode != null) {  // Only operate when mActionMode is available

                        mActionMode.finish();
                        mActionMode = null;
                    }
                }
            }
        });

        TextView tvTop = (TextView)convertView.findViewById(R.id.row_text_top);
        TextView tvBottom = (TextView)convertView.findViewById(R.id.row_text_bottom);
        tvTop.setText(mChildren.get(groupPosition).get(childPosition));
        tvBottom.setText(mChildrenSize.get(groupPosition).get(childPosition));
        return convertView;
    }

Autres conseils

Ce travail de volonté dans SDK 7 (Android 2.1) et plus. (Avec SherlockActionBar)

Totaly mimétique expérience gmail listbox.

I override onTouchEvent si la presse dans le côté d'angle gauche va activer le mode de sélection; Mutch mieux alors essayer de cliquer sur le petit cheackbox.

Je performItemClick passer outre si pressante pas dans la gauche agira comme une action de presse.

J'Override setItemChecked il mettra à jour mActionMode au besoin.

public class SelectListView extends ListView {

    private SherlockFragmentActivity mActivity;
    ActionMode mActionMode;

      public SelectListView(Context context) {
    this( context, null, 0); 
}

public SelectListView(Context context, AttributeSet attrs) {   
    this( context, attrs, 0); 
}   


public SelectListView(Context context, AttributeSet attrs, int defStyle) {
    super( context, attrs, defStyle ); 
    setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
    mActivity = (SherlockFragmentActivity) context;
}

    @Override
    public boolean performItemClick(View view, int position, long id) {
        OnItemClickListener mOnItemClickListener = getOnItemClickListener();
        if (mOnItemClickListener != null) {
            playSoundEffect(SoundEffectConstants.CLICK);
            if (view != null)
                view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
            mOnItemClickListener.onItemClick(this, view, position, id);
            return true;
        }
        return false;
    }

    boolean mSelectionMode = false;
    int mStartPosition;

    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        final int action = ev.getAction();
        final int x = (int) ev.getX();
        final int y = (int) ev.getY();

        if (action == MotionEvent.ACTION_DOWN && x < getWidth() / 7) {
            mSelectionMode = true;
            mStartPosition = pointToPosition(x, y);
        }
        if (!mSelectionMode)
            return super.onTouchEvent(ev);
        switch (action) {
        case MotionEvent.ACTION_DOWN:
            break;
        case MotionEvent.ACTION_MOVE:
            if (pointToPosition(x, y) != mStartPosition)
                mSelectionMode = false;
            break;
        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
        default:
            mSelectionMode = false;
            int mItemPosition = pointToPosition(x, y);
            if (mStartPosition != ListView.INVALID_POSITION)
                setItemChecked(mItemPosition, !isItemChecked(mItemPosition));
        }

        return true;
    }

    @Override
    public void setItemChecked(int position, boolean value) {
        super.setItemChecked(position, value);
        // boolean r = getAdapter().hasStableIds();
        int checkedCount = getCheckItemIds().length;

        if (checkedCount == 0) {
            if (mActionMode != null)
                mActionMode.finish();
            return;
        }
        if (mActionMode == null)
            mActionMode = mActivity.startActionMode(new ModeCallback());

        mActionMode.setTitle(checkedCount + " selected");

    }

    class ModeCallback implements ActionMode.Callback {

        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {

            menu.add(getResources().getString(R.string.aBar_remove)).setIcon(R.drawable.ic_action_trash)
                    .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);

            return true;
        }

        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            return true;
        }

        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            Toast.makeText(mActivity, "Delted  items", Toast.LENGTH_SHORT).show();
            mode.finish();
            return true;
        }

        @Override
        public void onDestroyActionMode(ActionMode mode) {
            mActionMode = null;
            clearChecked();
        }

    }

    public void clearChecked() {
        SparseBooleanArray CItem = getCheckedItemPositions();
        for (int i = 0; i < CItem.size(); i++)
            if (CItem.valueAt(i))
                super.setItemChecked(CItem.keyAt(i), false);
    }

}

vous pouvez utiliser un adaptateur listbox dont vous avez besoin.

si vous avez une case à cocher sur votre list_item_layout besoin de Tou mesure votre carte comme ceci:

ArrayAdapter<String> mAdapter = new ArrayAdapter<String>(this, R.layout.simple_list_item_multiple_choice,
            R.id.text1, Cheeses.sCheeseStrings) {

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View v = super.getView(position, convertView, parent);
            CheckBox checkBox = (CheckBox) v.findViewById(R.id.CheckBox);
            checkBox.setChecked(((ListView)parent).isItemChecked(position));
            return v;
        }

    };

Ne pas oublier d'utiliser android: background = "? Attr / activatedBackgroundIndicator" sur votre list_item_layout.xml

Dans l'utilisation de la réponse de plus tocnbuff410 le code suivant à la mise à jour cochés nombre

public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
    ++checkBoxCount;
 } else {
    --checkBoxCount;
 }
...

if (mActionMode != null) {
    mActionMode.setSubtitle(checkBoxCount + " item(s) selected.");
}

Je peux confirmer que le code suivant ne fonctionnerait pas sur les cases à cocher de listviews personnalisés. Cependant, à long presse fonctionne encore:

listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new ModeCallback());

Sélection case ListView personnalisée ne déclencherait pas actionmode. Seulement listviews par exemple intégré extension ListActivity ferait automatiquement.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top