2012-08-31 13 views
7

この問題の調査に数日を費やした後、ついにこの問題をあきらめて投稿します。同様の質問がここで(部分的に)解決され、解決策が提案されましたが、最終的に私を助けなかったのです。議論のトピックと私の問題に違いがあるように思わ:他人の非リストを養うためにSimpleCursorTreeAdapterを使用しているようだ...SimpleCursorTreeAdapterを使用してExpandableListActivityの折りたたみ状態を保存して復元します

問題:私のデバイス(サムスンギャラクシーS)の向きを変え、グループの展開状態は保持されずに復元されます。すべてのグループが閉じられ、リストが一番上にスクロールされます。

この問題は、すでにAndroid 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を使用して実施例を提供しているものを指すことができます展開/折りたたみ状態の復元?

(注:上記のアクティビティコードでこの問題を再現するには、あなたがandroid.permission.READ_CONTACTSに許可を提供する必要があります)

+2

これはよく形成された質問です! – giZm0

+0

異なるAndroidバージョンでこの問題を複数回デバッグした後、私は直接解決策をあきらめます。私は最後に** listState **がonRestoreInstanceState()で正しく埋められない理由を見つけることができませんでした。 これで、私はhttp://stackoverflow.com/questions/4184556/save-and-restore-expanded-collapsed-state-of-an-expandablelistactivityに記載されている明示的な解決策を使用しています これは私の問題ではうまくいきます。 – Michael

答えて

0

これは私たちのより綿密なプログラマの一部からの軽蔑を描くかもしれませんが、あなたは、単に作っ試してみましたあなたの州のコンテナはstaticオブジェクトですか?しかし、それ以前でさえ、おそらく、オブジェクトを取得した後にどこかにnotifydatasetchanged()を追加すると恩恵を受ける可能性があります。

関連する問題