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>
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]
Groupe 2 [index = 4]
Groupe 3 [index = 8]
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;
}
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;
}
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;
}
});
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.
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>
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.
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.
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;
}
});
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;
}
});
}
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;
}
});
}