Выделение выделенного элемента в расширяемом списке
У меня есть макет, где у меня есть расширяемый список в фрагменте слева и фрагмент деталей справа. Все это прекрасно работает.
Теперь я хотел бы указать, какой элемент слева содержит данные, показанные справа, и здесь у меня проблема.
В обычном виде списка я достиг этого, установив режим выбора для представления списка в одиночный, а затем используя состояние, которое можно вывести на основе "активированного" состояния. Когда я нажимаю элемент, фон устанавливается на мой выбранный цвет и остается таким, пока я не выберу другой элемент в списке.
Я попытался применить это к моему расширяемому списку, и это был/был мрачный сбой. Ошибок не было, но выбранный элемент не поддерживал его состояние цвета. Я не уверен, что я не правильно настрою режим выбора (я пробовал его в файле макета, а также программно, это, похоже, не имеет значения), или указывая на неправильную вещь (не знаю, как это могло быть, но...)
Любая помощь/указатели оценивается (даже если она находится в совершенно другом направлении).
Самый текущий сбой:
расширяемый код списка
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>
Ответы
Ответ 1
В ExpandableListView выполните следующие действия:
Шаг 1. Установите режим выбора в одиночный (можно сделать в xml как android: choiceMode = "singleChoice" )
Шаг 2. Используйте селектор xml в качестве фона (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>
Шаг 3. Вызовите expandableListView.setItemChecked(index, true) в обратном вызове onChildClick().
index - это индекс, основанный на 0 дочернего элемента, рассчитанный следующим образом
Группа 1 [index = 0]
- Детский элемент 1
- Детский элемент 2
- Детский элемент 3 [index = 3]
Группа 2 [index = 4]
- Детский элемент 1
- Детский элемент 2
- Детский элемент 3 [index = 7]
Группа 3 [index = 8]
- Детский элемент 1
- Детский элемент 2
- Детский элемент 3 [index = 11]
Если у нас есть заголовки списков, они также учитывают значения индекса.
Вот рабочий пример:
@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;
}
Ответ 2
Проведя 3-4 часа, стало так просто не создавать лишние XML файлы, просто проверьте, расширяется ли элемент группы, если да, затем выберите цвет, а в другом - сделать их такими, каковы они...
@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;
}
Ответ 3
Наконец-то я понял, как сделать эту работу (для меня). Кажется, это немного взломанный, но это единственное, что мне удалось найти для этого.
В основном я создаю двухмерный массив, чтобы удерживать выбранное состояние дочерних элементов, инициализировать его в конструкторе адаптера, тогда я ссылаюсь на это в моем методе getChildView
(в случае, если текущий выбранный ребенок прокручивается из поля зрения) и мой onChildClick
(изменить текущий выбор и отключить старый).
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
Конструктор инициализирует массив
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, необходимый для того, когда ребенок прокручивается вне поля зрения
@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 изменить выбранный элемент
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;
}
});
Ответ 4
У меня была такая же проблема, я исправил это, добавив
v.setSelected(true);
здесь образец моего кода:
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);
}
мой элемент 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>
android:drawSelectorOnTop="true"
в элементе ExpandableListView в XML файле (не дочернем элементе или группе):
<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>
Ответ 5
Следующее решение поможет вам создать другой селектор списка для группы и ребенка.
Прежде всего, вам нужно отключить селектор списков для ExpendableListView:
...
<ExpandableListView
...
android:listSelector="@android:color/transparent"
...
/>
...
После этого вам нужно скопировать пустой списокSelector. Вы можете сделать это вам нравится
...
private Drawable empty;
...
// binding view here. Name of ExpandableListView will be elv
empty = elv.getSelector();
Теперь нам нужно знать, когда мы включим селектор списков или отключим его. Для этого вам следует добавить следующие изменения для адаптера:
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;
}
});
...
}
...
}
Это все. Надеюсь, что это решение не оставляет времени.
Ответ 6
Если вам нужно изменить только цвет дочернего элемента, чем в методе onchildclick
, установите цвет фона в представление v.
@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
// TODO Auto-generated method stub
v.setBackgroundColor(Color.RED);
}
чтобы установить isChildSelectable
в true в адаптере.
Ответ 7
Вы можете сохранить текущий вид и изменить цвет фона для просмотра в своих кликах:
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;
}
});
Ответ 8
Это простое решение помогло мне, когда я столкнулся с тем же вопросом, что и автор
У меня есть макет, где у меня есть расширяемый список в фрагменте на слева и фрагмент деталей справа. Все это прекрасно работает. Сейчас я хотел бы указать, какой элемент слева содержит данные показано справа, и здесь у меня проблема.
Чтобы указать, какой элемент в расширяемом списке выбран, перейдите в свойства ExpandableListView (в макете) и выберите цвет для спискаSelector.
Ответ 9
просто используйте ниже
<ExpandableListView
android:id="@+id/expandable_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:childDivider="#474043"
android:groupIndicator="@null"
android:listSelector = "@drawable/item_selector"
android:background="#555"
android:drawSelectorOnTop="true"
android:textFilterEnabled="true"
/>
и ваш item_selector.xml следующим образом
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/selection_color_for_ex_list" android:state_pressed="true"/>
<item android:drawable="@color/selection_color_for_ex_list" android:state_selected="true"/>
<item android:drawable="@color/selection_color_for_ex_list" android:state_focused="true"/>
</selector>