Android Extend BaseExpandableListAdapter

时间:2010-03-26 23:46:36

标签: android

我正在尝试扩展BaseExpandableListAdapter,但是当我查看列表并选择要扩展的其中一个元素时,列表的顺序会反转。例如,如果我有一个包含4个元素的列表并选择第1个元素,则顺序(从上到下)现在为4,3,2,1,第4个元素(现在位于顶部)展开。如果我对第4个元素进行了扩展,则该顺序将恢复为1,2,3,4,而不包含扩展元素。

这是我的实施:

public class SensorExpandableAdapter extends BaseExpandableListAdapter {

    private static final int FILTER_POSITION = 0;
    private static final int FUNCTION_POSITION = 1;
    private static final int NUMBER_OF_CHILDREN = 2;
    ArrayList<SensorType> mParentGroups;
    private Context mContext;
    private LayoutInflater mInflater;

    public SensorExpandableAdapter(ArrayList<SensorType> parentGroup, Context context) {
        mParentGroups = parentGroup;
        mContext = context;
        mInflater = LayoutInflater.from(mContext);
    }
    @Override
    public Object getChild(int groupPosition, int childPosition) {
        // TODO Auto-generated method stub
        if(childPosition == FILTER_POSITION) return "filter";
        else return "function";
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition,
            boolean isLastChild, View convertView, ViewGroup parent) {
        if(convertView == null)
        {
            convertView = (RelativeLayout)mInflater.inflate(R.layout.sensor_row_list_item, parent, false);
            if(childPosition == FILTER_POSITION) {
                ((CheckBox)convertView.findViewById(R.id.chkTextAddFilter)).setText("Add Filter");
            } else {
                ((CheckBox)convertView.findViewById(R.id.chkTextAddFilter)).setText("Add Function"); 
                ((CheckBox)convertView.findViewById(R.id.chkTextAddFilter)).setEnabled(false);
            }
        }
        return convertView;
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        // TODO Auto-generated method stub
        return NUMBER_OF_CHILDREN;
    }

    @Override
    public Object getGroup(int groupPosition) {
        return mParentGroups.get(groupPosition);
    }

    @Override
    public int getGroupCount() {
        // TODO Auto-generated method stub
        return mParentGroups.size();
    }

    @Override
    public long getGroupId(int groupPosition) {
        // TODO Auto-generated method stub
        return groupPosition;
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded,
            View convertView, ViewGroup parent) {
        if(convertView == null)
        {
            convertView = mInflater.inflate(android.R.layout.simple_expandable_list_item_1, parent, false);
            TextView tv = ((TextView)convertView.findViewById(android.R.id.text1));
            tv.setText(mParentGroups.get(groupPosition).toString());
        }
        return convertView;
    }

    @Override
    public boolean hasStableIds() {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        // TODO Auto-generated method stub
        return true;
    }
}

`

我只需要使用我自己的SensorType类的简单ArrayList。所有班级的孩子都是一样的,只有两个。

另外,如何在每个组LongClickable中创建父级?我已经尝试使用此getExpandableListView().setOnLongClickableListener() ...在我的ExpandableListActivity中,并在父TextView上设置了它的OnLongClickableListener,但都不起作用。

非常感谢任何一方的帮助!

4 个答案:

答案 0 :(得分:3)

public View getGroupView(int groupPosition, boolean isExpanded,
            View convertView, ViewGroup parent) {
        if(convertView == null)
        {

只需注释掉“如果”。这应该有所帮助。

答案 1 :(得分:1)

更新:这个答案来得太晚了;但对于有同样问题的人,这是我的解决方案。

我遇到了同样的问题,并在阅读完chome2phone源代码后设法解决了这个问题。

关键在于这种方法:

public View getChildView(int groupPosition, int childPosition,
            boolean isLastChild, View convertView, ViewGroup parent) {
        if(convertView == null)
        {
            convertView = (RelativeLayout)mInflater.inflate(R.layout.sensor_row_list_item, parent, false);
            if(childPosition == FILTER_POSITION) {
                ((CheckBox)convertView.findViewById(R.id.chkTextAddFilter)).setText("Add Filter");
            } else {
                ((CheckBox)convertView.findViewById(R.id.chkTextAddFilter)).setText("Add Function"); 
                ((CheckBox)convertView.findViewById(R.id.chkTextAddFilter)).setEnabled(false);
            }
        }
        return convertView;
    }

AS @Dan说,convertView是一个缓存项目,documentation说:

  

convertView :如果可能,将旧视图重用。   您应该检查此视图是否正确   非null和适当的类型   在使用之前。如果不可能的话   转换此视图以显示   正确的数据,这种方法可以创建一个   新观点。不能保证   convertView将会是   以前创建的   getChildView(int,int,boolean,View,   ViewGroup中)。

在我的例子中,传递给getChildView()的对象可能来自缓存,其顺序与创建顺序完全相反;堆栈可能(LIFO)。

主要有两种解决方案;你要么删除

  

if(convertView == null)

因此在每次展开/折叠动作或每次方向改变时重新创建孩子,或者(方式更好的表现)做一些事情:

public View getChildView(int groupPosition, int childPosition,boolean isLastChild, View convertView, ViewGroup parent) {
    RelativeLayout mItemView;
    if (null == convertView || !(convertView instanceof RelativeLayout)) {
        mItemView = (RelativeLayout)mInflater.inflate(R.layout.sensor_row_list_item, parent, false);
    }else{
        mItemView = (RelativeLayout) convertView;
    }
    if(childPosition == FILTER_POSITION) {
        ((CheckBox)convertView.findViewById(R.id.chkTextAddFilter)).setText("Add Filter");
    } else {
        ((CheckBox)convertView.findViewById(R.id.chkTextAddFilter)).setText("Add Function"); 
        ((CheckBox)convertView.findViewById(R.id.chkTextAddFilter)).setEnabled(false);
    }
}
return convertView;

这意味着您将使用convertView对象渲染项而不是创建新项。

我希望这也适合你。

答案 2 :(得分:1)

我希望这是您正在寻找的答案

public class Sample extends ExpandableListActivity {

    ExpandableListAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
          mAdapter = new MyExpandableListAdapter();
          setListAdapter(mAdapter);
          registerForContextMenu(getExpandableListView());
    }

   @Override
public void onCreateContextMenu(ContextMenu menu, View v,
        ContextMenuInfo menuInfo) {
    // TODO Auto-generated method stub
    super.onCreateContextMenu(menu, v, menuInfo);

      menu.setHeaderTitle("Sample menu");
      menu.add(0, 0, 0, R.string.expandable_list_sample_action);

}

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        // TODO Auto-generated method stub

         ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) item.getMenuInfo();

         String title = ((TextView) info.targetView).getText().toString();



         int type = ExpandableListView.getPackedPositionType(info.packedPosition);

         if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
             int groupPos = ExpandableListView.getPackedPositionGroup(info.packedPosition); 
             int childPos = ExpandableListView.getPackedPositionChild(info.packedPosition); 
             Toast.makeText(Sample.this, title + ": Child " + childPos + " clicked in group " + groupPos,
                     Toast.LENGTH_SHORT).show();
             return true;
         } else if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
             int groupPos = ExpandableListView.getPackedPositionGroup(info.packedPosition); 
             Toast.makeText(this, title + ": Group " + groupPos + " clicked", Toast.LENGTH_SHORT).show();
             return true;
         }

         return false;

    }
    /**
     * A simple adapter which maintains an ArrayList of photo resource Ids. 
     * Each photo is displayed as an image. This adapter supports clearing the
     * list of photos and adding a new photo.
     *
     */
    public class MyExpandableListAdapter extends BaseExpandableListAdapter {
        // Sample data set.  children[i] contains the children (String[]) for groups[i].
        private String[] groups = { "People Names", "Dog Names", "Cat Names", "Fish Names" };
        private String[][] children = {
                { "Arnold", "Barry", "Chuck", "David" },
                { "Ace", "Bandit", "Cha-Cha", "Deuce" },
                { "Fluffy", "Snuggles" },
                { "Goldy", "Bubbles" }
        };

        public Object getChild(int groupPosition, int childPosition) {
            return children[groupPosition][childPosition];
        }

        public long getChildId(int groupPosition, int childPosition) {
            return childPosition;
        }

        public int getChildrenCount(int groupPosition) {
            return children[groupPosition].length;
        }

        public TextView getGenericView() {
            // Layout parameters for the ExpandableListView
            AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
                    ViewGroup.LayoutParams.FILL_PARENT, 64);

            TextView textView = new TextView(Sample.this);
            textView.setLayoutParams(lp);
            // Center the text vertically
            textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
            // Set the text starting position
            textView.setPadding(36, 0, 0, 0);
            return textView;
        }

        public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
                View convertView, ViewGroup parent) {
            TextView textView = getGenericView();
            textView.setText(getChild(groupPosition, childPosition).toString());
            return textView;
        }

        public Object getGroup(int groupPosition) {
            return groups[groupPosition];
        }

        public int getGroupCount() {
            return groups.length;
        }

        public long getGroupId(int groupPosition) {
            return groupPosition;
        }

        public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
                ViewGroup parent) {
            TextView textView = getGenericView();
            textView.setText(getGroup(groupPosition).toString());
            return textView;
        }

        public boolean isChildSelectable(int groupPosition, int childPosition) {
            return true;
        }

        public boolean hasStableIds() {
            return true;
        }

    }}

答案 3 :(得分:1)

这是我的第一个stackoverflow.com -answer。

我今天正在努力解决这个问题,并尝试了之前帖子中提供的解决方案。

评论“if”-clause确实解决了问题,但我认为这不是推荐的解决方案。如此ListView视频(http://www.youtube.com/watch?v=wDBM6wVEO70)中所述,在处理大型数据集时,重复使用convertView至关重要。

我的解决方案非常简单,在我的案例中完美运行。我从之前提到的视频中得到了这个想法:

   public View getGroupView(int groupPosition, boolean isExpanded,
            View convertView, ViewGroup parent)     {

        // 1. Step: check if convertView can be re-used or if it should be created.

        if (convertView == null) {

                // create the view or inflate the view from xml here
                // Note: inlating is expensive process, so do it only if needed 
                //       (it's needed when convertView can not be re-used)
                //
                // TODO: your code here

        }

        // 2. Step: populate the convertView with correct data.
        // Correct data can be accessed through groupPosition.
        //
        // TODO: your code here

        return convertView;
    } 

我认为问题中提供的代码中缺少第二步?

我希望这可以帮助有同样问题的人。

  • 图奥马斯