2012-08-31 2 views
7

이제이 문제에 대한 조사에 며칠을 보내고 마침내이 질문을 게시하고 게시합니다. 비슷한 질문이 여기에 (부분적으로) 응답되었고 해결책이 제안되었지만 결국 그 중 아무도 나를 도왔습니다. 논의 된 주제와 내 문제에 대한 차이가있을 것 같다 : 다른 사람의 비는 목록을 피드에 SimpleCursorTreeAdapter를 사용하는 것 같다 ...SimpleCursorTreeAdapter를 사용하여 ExpandableListActivity의 접힌 상태를 저장하고 복원합니다.

문제 : 내 장치의 방향을 변경 (삼성 갤럭시 S), 그룹의 확장 상태가 유지되지 않고 복원됩니다. 모든 그룹이 닫히고 목록이 맨 위로 스크롤됩니다.

문제는 이미 API 데모에 표시됩니다. 당신이 그들을 설치 한 경우 :

보기 -> 확장 가능한 목록 -> 2. 커서 (사람) : 샘플을 시작하고, 그룹을 확장하고, 장치를 돌리면 검색 결과에 그룹이 접힌 상태로 표시됩니다. . 코드에서

아래, 나는 다음과 같은 한 :하여 API 데모 (ExpandableList2.java)에서 코드를 가져다가 onSaveInstantState(), onRestoreInstanceState()와 onResume의 구현과 확장(). 이 방법에 대한 구현은 다른 토론 스레드 ( How to preserve scroll position in an ExpandableListView)에서 가져 왔습니다.

import android.app.ExpandableListActivity; 
import android.content.AsyncQueryHandler; 
import android.content.ContentUris; 
import android.content.Context; 
import android.database.Cursor; 
import android.net.Uri; 
import android.os.Bundle; 
import android.os.Parcelable; 
import android.provider.ContactsContract.CommonDataKinds.Phone; 
import android.provider.ContactsContract.Contacts; 
import android.view.View; 
import android.widget.CursorTreeAdapter; 
import android.widget.ExpandableListView; 
import android.widget.SimpleCursorTreeAdapter; 

public class MainActivity extends ExpandableListActivity { 

private static final String LIST_STATE_KEY = "levelSelectListState"; 
private static final String LIST_POSITION_KEY = "levelSelectListPosition"; 
private static final String ITEM_POSITION_KEY = "levelSelectItemPosition"; 

private static final String[] CONTACTS_PROJECTION = new String[] { 
     Contacts._ID, Contacts.DISPLAY_NAME }; 
private static final int GROUP_ID_COLUMN_INDEX = 0; 

private static final String[] PHONE_NUMBER_PROJECTION = new String[] { 
     Phone._ID, Phone.NUMBER }; 

private static final int TOKEN_GROUP = 0; 
private static final int TOKEN_CHILD = 1; 

private static final class QueryHandler extends AsyncQueryHandler { 
    private CursorTreeAdapter mAdapter; 

    public QueryHandler(Context context, CursorTreeAdapter adapter) { 
     super(context.getContentResolver()); 
     this.mAdapter = adapter; 
    } 

    @Override 
    protected void onQueryComplete(int token, Object cookie, Cursor cursor) { 
     switch (token) { 
     case TOKEN_GROUP: 
      mAdapter.setGroupCursor(cursor); 
      break; 

     case TOKEN_CHILD: 
      int groupPosition = (Integer) cookie; 
      mAdapter.setChildrenCursor(groupPosition, cursor); 
      break; 
     } 
    } 
} 

public class MyExpandableListAdapter extends SimpleCursorTreeAdapter { 

    // Note that the constructor does not take a Cursor. This is done to 
    // avoid querying the 
    // database on the main thread. 
    public MyExpandableListAdapter(Context context, int groupLayout, 
      int childLayout, String[] groupFrom, int[] groupTo, 
      String[] childrenFrom, int[] childrenTo) { 

     super(context, null, groupLayout, groupFrom, groupTo, childLayout, 
       childrenFrom, childrenTo); 
    } 

    @Override 
    protected Cursor getChildrenCursor(Cursor groupCursor) { 
     // Given the group, we return a cursor for all the children within 
     // that group 

     // Return a cursor that points to this contact's phone numbers 
     Uri.Builder builder = Contacts.CONTENT_URI.buildUpon(); 
     ContentUris.appendId(builder, 
       groupCursor.getLong(GROUP_ID_COLUMN_INDEX)); 
     builder.appendEncodedPath(Contacts.Data.CONTENT_DIRECTORY); 
     Uri phoneNumbersUri = builder.build(); 

     mQueryHandler.startQuery(TOKEN_CHILD, groupCursor.getPosition(), 
       phoneNumbersUri, PHONE_NUMBER_PROJECTION, Phone.MIMETYPE 
         + "=?", new String[] { Phone.CONTENT_ITEM_TYPE }, 
       null); 

     return null; 
    } 
} 

private QueryHandler mQueryHandler; 
private CursorTreeAdapter mAdapter; 
private Parcelable listState; 
private int listPosition; 
private int itemPosition; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    // Set up our adapter 
    mAdapter = new MyExpandableListAdapter(
      this, 
      android.R.layout.simple_expandable_list_item_1, 
      android.R.layout.simple_expandable_list_item_1, 
      new String[] { Contacts.DISPLAY_NAME }, // Name for group 
                // layouts 
      new int[] { android.R.id.text1 }, 
      new String[] { Phone.NUMBER }, // Number for child layouts 
      new int[] { android.R.id.text1 }); 

    setListAdapter(mAdapter); 

    mQueryHandler = new QueryHandler(this, mAdapter); 

    // Query for people 
    mQueryHandler.startQuery(TOKEN_GROUP, null, Contacts.CONTENT_URI, 
      CONTACTS_PROJECTION, Contacts.HAS_PHONE_NUMBER + "=1", null, 
      null); 
} 

@Override 
protected void onDestroy() { 
    super.onDestroy(); 

    // Null out the group cursor. This will cause the group cursor and all 
    // of the child cursors 
    // to be closed. 
    mAdapter.changeCursor(null); 
    mAdapter = null; 
} 

@Override 
protected void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 

    ExpandableListView listView = this.getExpandableListView(); 
    listState = listView.onSaveInstanceState(); 
    outState.putParcelable(LIST_STATE_KEY, listState); 

    listPosition = listView.getFirstVisiblePosition(); 
    outState.putInt(LIST_POSITION_KEY, listPosition); 

    View itemView = listView.getChildAt(0); 
    itemPosition = itemView == null ? 0 : itemView.getTop(); 
    outState.putInt(ITEM_POSITION_KEY, itemPosition); 
} 

@Override 
protected void onRestoreInstanceState(Bundle state) { 
    super.onRestoreInstanceState(state); 

    listState = state.getParcelable(LIST_STATE_KEY); 
    listPosition = state.getInt(LIST_POSITION_KEY); 
    itemPosition = state.getInt(ITEM_POSITION_KEY); 
} 

@Override 
protected void onResume() { 
    super.onResume(); 

    ExpandableListView listView = this.getExpandableListView(); 
    if (listView != null) { 
     if (listState != null) { 
      // yes, this code is reached 
      listView.onRestoreInstanceState(listState); 
      listView.setSelectionFromTop(listPosition, itemPosition); 
     } 
    } 
} 
} 

디버거를 사용하여 장치 방향을 변경하면 이러한 모든 메서드가 실제로 올바른 순서로 호출됩니다. 그러나 : 상태 복원은 효과가 없습니다. 그것에

또한 디버깅, I는 outState 빠르 onSaveInstanceState에서 listState()는 그것의 배열의 데이터를 포함하는 반면 onRestoreInstanceState에서 복원 listState()의 내용이 비어있는 배열을 포함하였습니다.

그래서 내 가정이다는 listState Parcelable이 지속되거나 시스템이 제대로 검색되지 않는다는 것을 ...

사람이 잘못된 것, 또는 "작업"으로 SimpleCursorTreeAdapter를 사용하여 작업 예제를 제공 무엇을 지적 할 수 확장/축소 상태 복원?

이 우리의 더 꼼꼼한 프로그래머의 일부로부터 경멸을 그릴 수

+2

이것은 잘 형성된 질문입니다! – giZm0

+0

다른 Android 버전에서이 문제를 여러 번 디버깅 한 후 직접 해결 방법을 포기합니다. 마침내 ** listState **가 onRestoreInstanceState()에서 올바르게 채워지지 않은 이유를 찾을 수 없습니다. 이제는 http://stackoverflow.com/questions/4184556/save-and-restore-expanded-collapsed-state-of-an-expandablelistactivity에 명시된 명시 적 솔루션을 사용하고 있습니다. 내 문제는 잘 해결됩니다. . – Michael

답변

0

(참고 위의 활동 코드와이 문제를 재현하려면 android.permission.READ_CONTACTS 권한을 제공해야합니다),하지만 당신은 간단하게 시도 귀하의 주 컨테이너는 static 개체입니까? 그러나 그 전에도 객체를 검색 한 후에 어딘가에 notifydatasetchanged()을 추가하면 도움이 될 수 있습니다.

관련 문제