将选中的项目移动到可扩展列表视图中

时间:2013-01-14 22:24:47

标签: android expandablelistview move expandablelistadapter

我面临着ExpandableListView的一个大问题。 我的目标是让用户将项目的位置更改为此单一选择可扩展列表视图:

enter image description here

当用户点击某个项目时,该项目将被选中并显示上下文操作栏。 因此,用户可以通过这种方式向上或向下移动项目:

enter image description here

我实现的上移/下移功能工作正常(它基于ArrayList上的交换位置,这是我的BaseExpandableListAdapter的数据源,并通知对UI的更改)。不幸的是,当我移动一个已检查的项目时,它会丢失已检查的状态...并且如果我将项目移出可见边界(在示例中,在“已锁定”之后或“附加”视图之前),则expandablelistview不会滚动到新职位。

我如何实现这一目标?

下面,我的“moveDownFocusedItem()”编码到我的自定义适配器类中:

 //This class is ok!
 //Contains Group and Child position of an ExpandableListView
 public class Position{
    int GroupPosition;
    int ChildPosition;

    public boolean isChild(){
        return (ChildPosition != AbsListView.INVALID_POSITION);
    }


    public Position getPreviousPosition(){
        if(ChildPosition==AbsListView.INVALID_POSITION)
            if(GroupPosition>0)
                return new Position(GroupPosition-1);
            else
                return null;
        else
            if(ChildPosition>0)
                return new Position(GroupPosition, ChildPosition-1);
            else
                return null;
    }


    public Position getNextPosition(){
        if(ChildPosition==AbsListView.INVALID_POSITION)
            if(GroupPosition<_fieldConfigurationList.size()-1)
                return new Position(GroupPosition+1);
            else
                return null;
        else
              if(ChildPosition<_fieldConfigurationList.get(GroupPosition).getChildren().size()-1)
                return new Position(GroupPosition, ChildPosition+1);
            else
                return null;
    }

    public Position(int groupPosition){
        this.GroupPosition = groupPosition;
        this.ChildPosition = AbsListView.INVALID_POSITION;
    }

    public Position(int groupPosition, int childPosition){
        this.GroupPosition = groupPosition;
        this.ChildPosition = childPosition;
    }
}


public void moveDownFocusedItem(){

    //This function returns the next position to move to 
    //(_focusedPosition is the current checked item position)
    Position nextPosition = this._focusedPosition.getNextPosition();

    //Swap ArrayList (This works!)
    if(nextPosition!=null){ 
        Collections.swap(this._fieldConfigurationList,  //that's my datasource
                         this._focusedPosition.GroupPosition,  //Start position for swapping
                         nextPosition.GroupPosition);   //Destination position for swapping

    //Set the new focused position (This works!)
    this._focusedPosition = nextPosition;

    //TODO:
    //Now i have to call "SetItemChecked()" method to uncheck old focused position and check the new one.
    //How to do it? How can i get the required "position" argument from _focusedPosition.GroupPosition and _focusedPosition.ChildPosition?
    //And also...if the focused view has moved to an invisible position (such as the end of the expandablelistview) how can i scroll 
    //to this position?

    //Notify changes (This works!)
    this.notifyDataSetChanged();

    }
}

1 个答案:

答案 0 :(得分:1)

在研究了expandablelistview背后的代码之后,我发现了一种非常简单的方法来完成所需的任务。我将发布我的适配器的一部分,它允许检查列表视图项并上下移动它。 记得: 1)确保您的expandablelistview处于“单选”模式(ExpandableListView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);)

2)你的自定义行视图有android:descendantFocusability =“blocksDescendants”

我已经对android J.B做了几次测试,似乎没有错误或内存泄漏正常工作。 如果有错误,请发布改进或修复。 这是我的代码:

public class MyAdapter extends BaseExpandableListAdapter {

//protected ArrayList<Object> _list; //TODO: Replace with your datasource
private ExpandableListView _expandableListView;
private long _checkedPosition;

public long getCheckedPosition(){
    return _checkedPosition;
}
public void setCheckedPosition(int groupPosition){
    long packedPosition = ExpandableListView.getPackedPositionForGroup(groupPosition);
    this.setCheckedPosition(packedPosition);
}
public void setCheckedPosition(int groupPosition, int childPosition){
    long packedPosition = ExpandableListView.getPackedPositionForChild(groupPosition, childPosition);
    this.setCheckedPosition(packedPosition);
}
public void setCheckedPosition(long position){
    final int flatPosition;

    //Gets flat position
    flatPosition = _expandableListView.getFlatListPosition(position);

    //Set the new position, checked and focused
    _expandableListView.setItemChecked(flatPosition , true);
    _checkedPosition = position;

    //If it's out of bounds, set focus on it and force scroll (postpone because row's views may not exists yes)
    if(flatPosition<_expandableListView.getFirstVisiblePosition() || 
       flatPosition>_expandableListView.getLastVisiblePosition())
        _expandableListView.post(new Runnable() {

            @Override
            public void run() {
                _expandableListView.setSelection(flatPosition);     
            }
        });
}

public void clearCheckedPosition(){
    final int flatPosition;

    flatPosition = _expandableListView.getFlatListPosition(getCheckedPosition());
    _expandableListView.setItemChecked(flatPosition , false);
}


private long getPreviousPosition(long position){
    int group = ExpandableListView.getPackedPositionGroup(position);
    int child = ExpandableListView.getPackedPositionChild(position);

    if(child==-1)
        if(group>0)
            return ExpandableListView.getPackedPositionForGroup(group-1); 
        else
            return -1;
    else
        if(child>0)
            return ExpandableListView.getPackedPositionForChild(group, child-1);
        else
            return -1;
}

private long getNextPosition(long position){
    int group = ExpandableListView.getPackedPositionGroup(position);
    int child = ExpandableListView.getPackedPositionChild(position);

    if(child==-1)
        if(group<getGroupCount()-1)
            return ExpandableListView.getPackedPositionForGroup(group+1);
        else
            return -1;
    else
        if(child<getChildrenCount(group)-1)
            return ExpandableListView.getPackedPositionForChild(group, child+1);
        else
            return -1;
}


public boolean canMoveUpCheckedItem(){

    if(getCheckedPosition()!=-1)
        if(getPreviousPosition(getCheckedPosition())!=-1)
            return true;
    return false;
}

public boolean canMoveDownCheckedItem(){
    if(getCheckedPosition()!=-1)
        if(getNextPosition(getCheckedPosition())!=-1)
            return true;
    return false;
}


public void moveUpFocusedItem(){

    long prevPosition = this.getPreviousPosition(getCheckedPosition());
    if(prevPosition!=-1L){  
        //Swap position
        switch(ExpandableListView.getPackedPositionType(getCheckedPosition())){
        case ExpandableListView.PACKED_POSITION_TYPE_GROUP:
            //Collapse group if expanded
            _expandableListView.collapseGroup(ExpandableListView.getPackedPositionGroup(getCheckedPosition()));

            //TODO:Implement group swap
            /*Collections.swap(this._list,
                             ExpandableListView.getPackedPositionGroup(getCheckedPosition()),
                             ExpandableListView.getPackedPositionGroup(prevPosition));*/
            break;

        case ExpandableListView.PACKED_POSITION_TYPE_CHILD:

            //TODO:Implement child swap
            /**Collections.swap(this._list.get(ExpandableListView.getPackedPositionGroup(getCheckedPosition())).getChildren(), 
                            ExpandableListView.getPackedPositionChild(getCheckedPosition()), 
                            ExpandableListView.getPackedPositionChild(prevPosition));**/
            break;

        }

        //Set new focused position
        this.setCheckedPosition(prevPosition);

        //Notify changes
        this.notifyDataSetChanged();

    }
}

public void moveDownFocusedItem(){
    long nextPosition =  this.getNextPosition(getCheckedPosition());
    if(nextPosition!=-1L){
        switch(ExpandableListView.getPackedPositionType(getCheckedPosition())){
        case ExpandableListView.PACKED_POSITION_TYPE_GROUP:
            //Collapse group if expanded
            _expandableListView.collapseGroup(ExpandableListView.getPackedPositionGroup(getCheckedPosition()));

            //TODO:Implement group swap
            /*Collections.swap(this._list, 
                             ExpandableListView.getPackedPositionGroup(getCheckedPosition()), 
                             ExpandableListView.getPackedPositionGroup(nextPosition));*/
            break;

        case ExpandableListView.PACKED_POSITION_TYPE_CHILD: 

            //TODO:Implement child swap
            /*Collections.swap(this._list.get(ExpandableListView.getPackedPositionGroup(getCheckedPosition())).getChildren(), 
                             ExpandableListView.getPackedPositionChild(getCheckedPosition()), 
                             ExpandableListView.getPackedPositionChild(nextPosition));*/
            break;
        }

        //Set new focused position
        this.setCheckedPosition(nextPosition);

        //Notify changes
        this.notifyDataSetChanged();

    }
}







@Override
public Object getChild(int groupPosition, int childPosition) {
    //TODO: Implement
}

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

@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
    //TODO: Implement
}

@Override
public int getChildrenCount(int groupPosition) {
    //TODO: Implement
}

@Override
public Object getGroup(int groupPosition) {
    //TODO: Implement
}

@Override
public int getGroupCount() {
    //TODO: Implement
}

@Override
public long getGroupId(int groupPosition) {
    return ExpandableListView.getPackedPositionForGroup(groupPosition);
}

@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
    //TODO: Implement your getGroupView
}

@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
    //TODO: Implement
}

@Override
public boolean hasStableIds() {
    //TODO: Implement
}

}