【问题标题】:Highlight for selected item in expandable list突出显示可展开列表中的选定项目
【发布时间】:2012-05-06 07:31:22
【问题描述】:

我有一个布局,其中左侧的片段中有一个可扩展列表,右侧有一个详细信息片段。这一切都很好。

现在我想指出左侧的哪个项目的详细信息显示在右侧,这里我遇到了问题。

在普通的列表视图中,我通过将列表视图的选择模式设置为单一然后使用基于“激活”状态的可绘制状态来实现这一点。当我单击该项目时,背景将设置为我选择的颜色并保持这种状态,直到我选择列表中的另一个项目。

我试图将它应用到我的可扩展列表视图中,但它是/现在是一个惨淡的失败。没有错误,但所选项目未保持其颜色状态。我不确定我是否没有为它正确设置选择模式(我已经在布局文件中以及以编程方式尝试过它,它似乎没有任何区别),或者将它指向错误的东西(不知道怎么可能,但是...)

感谢任何帮助/指针(即使它的方向完全不同)。

最新故障:

可扩展的列表视图代码

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>

【问题讨论】:

  • 你的问题是当你点击它时它很好,但是当你的列表视图向上或向下移动时它只是失去了颜色
  • 不,这不是我的问题。我的问题和我说的完全一样。我选择了该项目,但未保留突出显示。它会闪烁“按下”状态的颜色,但不会更改/保持“激活”状态的颜色。

标签: android android-layout android-widget


【解决方案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 步。 在 onChildClick() 回调中调用 expandableListView.setItemChecked(index,true)

index是从0开始计算的子项的索引

第 1 组 [索引 = 0]

  • 子项 1
  • 子项 2
  • 子项 3 [索引 = 3]

第 2 组 [索引 = 4]

  • 子项 1
  • 子项 2
  • 子项 3 [索引 = 7]

第 3 组 [索引 = 8]

  • 子项 1
  • 子项 2
  • 子项 3 [索引 = 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;
}

【讨论】:

  • 这很有帮助。为此,由于某种原因,我无法让 android:listSelector="@drawable/selector_list_item" 正常工作。我的解决方案是在列表上执行 android:listSelector="@android:color/transparent" 然后在列表中项目的实际布局中, android:background="@drawable/selector_list_item"
  • 嗨,getFlatListPosition(1,3) 总是返回 1 而不是子元素的平面位置。我想根据偏好数据设置 singleChoice ExpandableListView 的各种元素
  • 感谢此解决方案适用于可扩展列表视图中的子视图,谢谢!我们如何在可展开的列表视图中更改所选组的背景颜色。
  • 起初这对我不起作用,因为我在子项布局内的特定元素上设置了 onClickListeners。似乎他们覆盖了子点击监听器。
  • 如何使用它来突出显示多个项目
【解决方案2】:

花费 3-4 小时后,它变得如此简单,无需创建额外的 XML 文件,只需检查组项是否已扩展,如果是,则选择颜色并在 else 语句中使其保持原样....

@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;
            }
        });
    

    【讨论】:

    • 哇...好胖 =) 我找到了更轻量级的解决方案。看上面。
    • 是您的适配器在活动类中(嵌套)。你如何在lv.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { 中访问selectedStatus[][]
    • 这适用于自定义视图,如果我们需要更改某些精确视图,我们可以使用模型中的标志变量并这样做。
    【解决方案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>
    

    在 xml 文件的 ExpandableListView 元素(不是子项或组)中的属性android:drawSelectorOnTop="true" 如下所示:

    <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>
    

    【讨论】:

    • 我忘了指出 xml 文件中 ExpandableListView 元素中的属性 android:drawSelectorOnTop="true" 像这样
    【解决方案5】:

    下一个解决方案可帮助您为组和子创建不同的列表选择器。

    首先,您需要禁用 ExpendableListView 的列表选择器:

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

    之后,您需要复制一个空的 listSelector。你可以这样做

    ... 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】:

      您可以保存当前视图并在点击侦听器中更改视图的背景颜色:

      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;
          }
      });
      

      【讨论】:

        【解决方案7】:

        如果您只需要更改子项颜色,而不是在 onchildclick 方法中将背景颜色设置为 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);
        }
        

        为此,请在适配器中将 isChildSelectable 设置为 true。

        【讨论】:

          【解决方案8】:

          当我面临与作者相同的问题时,这个简单的解决方案帮助了我

          我有一个布局,其中的片段中有一个可扩展列表 左边和右边的细节片段。这一切都很好。现在我 想指出左边的哪个项目有它的详细信息 显示在右侧,我遇到了问题。

          要指示选择了可扩展列表中的哪个项目,请转到 ExpandableListView 属性(在布局中)并为 listSelector 选择颜色。

          【讨论】:

            【解决方案9】:
            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;
                        }
                    });
             }
            

            【讨论】:

              【解决方案10】:
              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;
                      }
                  });
              }
              

              【讨论】:

              【解决方案11】:

              只要使用下面的

                  <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>
              

              【讨论】:

              • 不起作用,因为它关闭了指示器而不是组的 listSelector
              • 帮助我了解了在哪里声明 listselector。赞成:)
              猜你喜欢
              • 1970-01-01
              • 2012-02-02
              • 1970-01-01
              • 1970-01-01
              • 2013-12-22
              • 1970-01-01
              • 1970-01-01
              • 2018-11-10
              • 2013-10-26
              相关资源
              最近更新 更多