web-dev-qa-db-fra.com

Mettre en surbrillance l'élément sélectionné dans la liste extensible

J'ai une mise en page où j'ai une liste extensible dans un fragment à gauche et un fragment de détails à droite. Tout cela fonctionne bien. 

Maintenant, je voudrais indiquer quel élément à gauche est que ses détails sont montrés à droite et ici, j'ai un problème.

Dans une vue de liste normale, j'ai atteint cet objectif en définissant le mode de choix de la vue de liste sur single, puis en utilisant un état pouvant être dessiné en fonction de l'état "activé". Lorsque je clique sur l'élément, l'arrière-plan est défini sur la couleur sélectionnée et le reste jusqu'à ce que je sélectionne un autre élément de la liste.

J'ai essayé d'appliquer cela à ma liste déroulante extensible et c'était/est un échec lamentable. Il n'y a pas eu d'erreur, mais l'élément sélectionné n'a pas conservé son état de couleur. Je ne suis pas sûr de ne pas définir correctement le mode de choix (je l'ai essayé dans le fichier de présentation ainsi que par programme, cela ne semble pas faire de différence), ou de le signaler au mauvais endroit. (Je ne sais pas comment cela pourrait être, mais ...)

Toute aide/pointeur apprécié (même si c'est dans une direction complètement différente).

L'échec le plus courant:

code de liste de diffusion extensible

private void fillData(String group, String child) {
    ExpandableListView lv;
    mGroupsCursor = mDbHelper.fetchGroup(group);
    getActivity().startManagingCursor(mGroupsCursor);
    mGroupsCursor.moveToFirst();
    lv = (ExpandableListView) getActivity().findViewById(R.id.explist);
    lv.setChoiceMode(ExpandableListView.CHOICE_MODE_SINGLE);        

    mAdapter = new MyExpandableListAdapter(mGroupsCursor, getActivity(),
            R.layout.explistlayout,
            R.layout.explistlayout,
            new String[] { "_id" },
            new int[] { Android.R.id.text1 },
            new String[] { child },
            new int[] { Android.R.id.text1 });
    lv.setAdapter(mAdapter);
    registerForContextMenu(lv);

    lv.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { 
        @Override 
        public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id)  
        { 
            mRowId  = id;
            EventDisplayFragment eventdisplay = new EventDisplayFragment();
            getFragmentManager().beginTransaction().replace(R.id.rightpane, eventdisplay).commit();
            return true; 
        } 
        }); 
}

public class MyExpandableListAdapter extends SimpleCursorTreeAdapter {

    public MyExpandableListAdapter(Cursor cursor, Context context,
            int groupLayout, int childLayout, String[] groupFrom,
            int[] groupTo, String[] childrenFrom, int[] childrenTo) {
        super(context, cursor, groupLayout, groupFrom, groupTo,
                childLayout, childrenFrom, childrenTo);
    }
    @Override
    protected Cursor getChildrenCursor(Cursor groupCursor) {
        Cursor childCursor = mDbHelper.fetchChildren(mGroup, groupCursor
                .getString(groupCursor
                        .getColumnIndex(AttendanceDB.EVENT_ROWID)));
        getActivity().startManagingCursor(childCursor);
        childCursor.moveToFirst();
        return childCursor;
    }
}

item_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item 
     Android:state_pressed="true" 
     Android:drawable="@color/green" />
    <item 
     Android:state_selected="true" 
     Android:drawable="@color/blue" />
    <item 
     Android:state_focused="true" 
     Android:drawable="@color/Violet" />
    <item 
     Android:state_activated="true" 
     Android:drawable="@color/blue" />
</selector>
13
Barak

Procédez comme suit sur ExpandableListView:

Étape 1. Définissez le mode choix sur single (peut être effectué au format xml en tant que Android: choiceMode = "singleChoice" )

Étape 2. Utilisez un sélecteur xml comme arrière-plan ( Android: listSelector = "@ drawable/selector_list_item" )

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android"
   Android:exitFadeDuration="@Android:integer/config_mediumAnimTime">

   <item Android:drawable="@Android:color/holo_blue_bright" Android:state_pressed="true"/>
   <item Android:drawable="@Android:color/holo_blue_light" Android:state_selected="true"/>
   <item Android:drawable="@Android:color/holo_blue_dark" Android:state_activated="true"/>

</selector>

Étape 3. Appel expandableListView.setItemChecked (index, true) dans le rappel onChildClick ().

index est un index basé sur 0 de l'élément enfant calculé comme suit

Groupe 1 [index = 0]

  • Article enfant 1
  • Article enfant 2
  • Item enfant 3 [index = 3]

Groupe 2 [index = 4]

  • Article enfant 1
  • Article enfant 2
  • Item enfant 3 [index = 7]

Groupe 3 [index = 8]

  • Article enfant 1
  • Article enfant 2
  • Item enfant 3 [index = 11]

Si nous avons également des en-têtes de liste, ils prendront également en compte les valeurs d'index.

Voici un exemple de travail:

@Override
public boolean onChildClick(ExpandableListView parent, View v,
        int groupPosition, int childPosition, long id) {
    ...

    int index = parent.getFlatListPosition(ExpandableListView.getPackedPositionForChild(groupPosition, childPosition));
    parent.setItemChecked(index, true);


    return true;
}
30
Himanshu Likhyani

Après avoir passé 3-4 heures, il est si simple qu'il n'est pas nécessaire de créer des fichiers XML supplémentaires. Il suffit de vérifier si l'élément de groupe est développé, si oui, sélectionnez ensuite la couleur et indiquez-les comme ils sont ....

@Override
//in this method you must set the text to see the parent/group on the list
public View getGroupView(final int i, boolean b, View view, ViewGroup viewGroup) {

    if (view == null) {
        view = inflater.inflate(R.layout.list_item_parent, viewGroup,false);
    }

    if(b){
        view.setBackgroundResource(R.color.waterblue);
    }else{
        view.setBackgroundColor(color.transparent);
    }


    //return the entire view
    return view;
}
12
Prakash Gavade

J'ai enfin compris comment faire ce travail (pour moi). Cela semble un peu du bidouillage, mais c'est la seule chose que j'ai réussi à obtenir pour travailler pour cela.

Fondamentalement, je crée un tableau à deux dimensions pour contenir l’état sélectionné des enfants, je l’initialise dans le constructeur de l’adaptateur, puis je le référence dans ma méthode getChildView (dans le cas où l’enfant actuellement sélectionné défile de vue) et ma méthode onChildClick (pour changer). la sélection actuelle et éteignez l’ancienne).

private selectedStatus[][];  // array to hold selected state
private View oldView;        // view to hold so we can set background back to normal after selection of another view

Constructeur initialise le tableau

    public MyExpandableListAdapter(Cursor cursor, Context context,
            int groupLayout, int childLayout, String[] groupFrom,
            int[] groupTo, String[] childrenFrom, int[] childrenTo) {
        super(context, cursor, groupLayout, groupFrom, groupTo,
                childLayout, childrenFrom, childrenTo);
        selectedStatus = new boolean[cursor.getCount()][];
        for (int i = 0; i < cursor.getCount(); i++) {
            cursor.moveToPosition(i);
            Cursor childCheckCursor = mDbHelper.fetchChildren(mGroup,
                    cursor.getString(cursor
                            .getColumnIndex(AttendanceDB.EVENT_ROWID)));
            getActivity().startManagingCursor(childCheckCursor);
            selectedStatus[i] = new boolean[childCheckCursor.getCount()];
            for (int j = 0; j < childCheckCursor.getCount(); j++) {
                selectedStatus[i][j] = false;
            }
        }

    }

getChildView nécessaire lorsque l'enfant ne fait pas défiler la vue

    @Override 
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { 
        final View v = super.getChildView(groupPosition, childPosition, isLastChild, convertView, parent); 
        if(selectedStatus[groupPosition][childPosition] == true){
            v.setBackgroundResource(R.color.blue);                          
        } else {
            v.setBackgroundResource(R.color.black);
        }
        return v; 
    } 

onChildClick change l'élément sélectionné

    lv.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
        @Override
        public boolean onChildClick(ExpandableListView parent, View v,
                int groupPosition, int childPosition, long id) {
            mRowId = id;
            EventDisplayFragment eventdisplay = new EventDisplayFragment();
            getFragmentManager().beginTransaction()
                    .replace(R.id.rightpane, eventdisplay).commit();
            if(oldView != null){
                oldView.setBackgroundResource(R.color.black);   // change the background of the old selected item back to default black                 }
            oldView = v;                                        // set oldView to current view so we have a reference to change back on  next selection
            for (int i = 0; i < selectedStatus.length; i++) {
                for (int j = 0; j < checkedStatus[i].length; j++) {
                    if(i == groupPosition && j == childPosition){  // set the current view to true and all others to false
                        selectedStatus[i][j] = true;
                    } else {
                        selectedStatus[i][j] = false;
                    }
                }
            }
            v.setBackgroundResource(R.color.blue);
            return true;
        }
    });
6
Barak

La solution suivante vous aide à créer un sélecteur de liste différent pour le groupe et l’enfant.

Tout d’abord, vous devez désactiver le sélecteur de liste pour ExpendableListView:


...
   <ExpandableListView
            ...
            Android:listSelector="@Android:color/transparent"
            ...
            />
...

Après, vous devez copier un listSelector vide. Vous pouvez faire comme ça


...
private Drawable empty;
...

// binding view here. Name of ExpandableListView will be elv
empty = elv.getSelector();

Maintenant, nous devons savoir quand nous activerons le sélecteur de liste ou le désactiver. Vous devez ajouter les modifications suivantes à votre adaptateur pour cela:


my adapter here {
...
    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View view, ViewGroup parent)
    {
       ...
       // after, we've got view of goup
       view.setOnTouchListener(new View.OnTouchListener()
       {
           @Override
           public boolean onTouch(View v, MotionEvent event)
           {
               elv.setSelector(empty);
               return false;
           }
       });
       ...
    }
...
    @Override
    public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, final ViewGroup parent)
    {
       ...
       // after, we've got view of child
       view.setOnTouchListener(new View.OnTouchListener()
       {
           @Override
           public boolean onTouch(View v, MotionEvent event)
           {
               elv.setSelector(R.drawable.my_custom_list_selector);
               return false;
           }
       });
       ...
    }
...
}

C'est tout. J'espère que cette solution garde votre temps.

2
Rusfearuth

J'avais le même problème que j'ai résolu en ajoutant 

v.setSelected(true);

voici un échantillon de mon code: 

expandableListDetailsLevel.setChoiceMode(ExpandableListView.CHOICE_MODE_SINGLE);
        expandableListDetailsLevel
                .setOnGroupExpandListener(new OnGroupExpandListener() {

                    public void onGroupExpand(int groupPosition) {

                        if(groupPosition!=1){
                            expandableIsThere = false;
                        }

                        for (int i = 0; i < len; i++) {
                            if (i != groupPosition) {
                                expandableListDetailsLevel.collapseGroup(i);
                            }
                        }
                    }
                });

        expandableListDetailsLevel
                .setOnChildClickListener(new OnChildClickListener() {

                    @Override
                    public boolean onChildClick(ExpandableListView parent,
                            View v, int groupPosition, int childPosition,
                            long id) {


                        v.setSelected(true);

                        }

mon article xml 

<?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="wrap_content"
Android:orientation="horizontal"
Android:background="@drawable/selector" >


<TextView
    Android:id="@+id/TVChild"
    Android:layout_width="fill_parent"
    Android:layout_height="match_parent"
    Android:textColor="#000"
    Android:textSize="12dp"/>

</LinearLayout>

attribuez Android:drawSelectorOnTop="true" dans l'élément ExpandableListView du fichier xml (pas l'élément enfant ou le groupe) comme ceci:

<ExpandableListView
                Android:id="@+id/expandableViewDetailsBriefing"
                Android:layout_width="fill_parent"
                Android:layout_height="match_parent"
                Android:background="#fff"
                Android:drawSelectorOnTop="true"
                Android:dividerHeight="1px"
                Android:childDivider="@color/Gris"
                Android:indicatorRight="690dp"
                Android:textFilterEnabled="true" >
            </ExpandableListView>
2
Driss Bounouar

Si vous souhaitez que seule la couleur de l'élément enfant soit modifiée par rapport à la méthode onchildclick, définissez la couleur d'arrière-plan sur View v.

@Override
            public boolean onChildClick(ExpandableListView parent, View v,
                    int groupPosition, int childPosition, long id) {
                // TODO Auto-generated method stub
                v.setBackgroundColor(Color.RED);
}

pour ce faire, définissez isChildSelectable sur true dans l'adaptateur.

1
user2779311

Cette solution simple m'a aidé lorsque j'étais confronté à la même question que l'auteur

J'ai une mise en page où j'ai une liste extensible dans un fragment à gauche du Et un fragment de détails à droite. Tout cela fonctionne bien. Maintenant, je voudrais indiquer quel élément à gauche affiche les détails à droite et je suis confronté à un problème.

Pour indiquer quel élément de la liste extensible est sélectionné, accédez aux propriétés ExpandableListView (dans la présentation) et choisissez une couleur pour listSelector. 

1
Ilya Shirokov

Vous pouvez enregistrer la vue actuelle et modifier la couleur de fond de la vue dans vos écouteurs de clic:

View currentView;
ExpandableListView elv;

elv.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
    @Override
    public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
        if(currentView != null) {
            currentView.setBackgroundColor(Color.parseColor("#FFFFFF"));
        }
        v.setBackgroundColor(Color.parseColor("#EEEEEE"));
        currentDrawerView = view;

        //do something

        return false;
    }
});
elv.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
    @Override
    public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
        if(currentView != null) {
            currentView.setBackgroundColor(Color.parseColor("#FFFFFF"));
        }
        v.setBackgroundColor(Color.parseColor("#EEEEEE"));
        currentDrawerView = view;

        //do something

        return false;
    }
});
1
expListView.setOnChildClickListener(new OnChildClickListener() {

        @Override
        public boolean onChildClick( ExpandableListView parent, View v,
                                     int groupPosition, int childPosition,
                                     long id) {



            for (int i = 1; i < expListView.getChildCount(); i++) {
                View child = (View) expListView.getChildAt(i);
                child.setBackgroundColor(Color.BLACK);
            }


            if(childPosition==0){
                initWebView("URL");

            }
            if(childPosition==1) {
                initWebView("URL");

            }
            if(childPosition==2) {

                initWebView("URL");

            }
            if(childPosition==3) {
                initWebView("URL");

            }
            if(childPosition==4) {
                initWebView("URL");

            }
            if(childPosition==5) {
                initWebView("URL");
            }

            v.setBackgroundColor(Color.GRAY);


            expListView.setVisibility(View.GONE);
            webView.setVisibility(View.VISIBLE);
            return false;
        }
    });
}
0
Taha Hyder
expListView.setOnChildClickListener(new OnChildClickListener() {

            @Override
            public boolean onChildClick( ExpandableListView parent, View v,
                                         int groupPosition, int childPosition,
                                         long id) {



                for (int i = 1; i < expListView.getChildCount(); i++) {
                    View child = (View) expListView.getChildAt(i);
                    child.setBackgroundColor(Color.BLACK);
                }


                if(childPosition==0){
                    initWebView("URL");

                }
                if(childPosition==1) {
                    initWebView("URL");

                }
                if(childPosition==2) {

                    initWebView("URL");

                }
                if(childPosition==3) {
                    initWebView("URL");

                }
                if(childPosition==4) {
                    initWebView("URL");

                }
                if(childPosition==5) {
                    initWebView("URL");
                }

                v.setBackgroundColor(Color.GRAY);


                expListView.setVisibility(View.GONE);
                webView.setVisibility(View.VISIBLE);
                return false;
            }
        });
 }
0
Taha Hyder