LoginSignup
3
5

More than 5 years have passed since last update.

Android:ListViewの画面回転と復元

Last updated at Posted at 2017-02-26

はじめに

ListViewを単純に実装した場合、画面回転しても、表示していたアイテムは保持されません。
そのため画面回転するたびに、アイテムを取得し直す必要があったり、スクロール位置が最上部に戻ってしまったり、といった問題が発生します。

この記事では、画面回転しても、スクロール位置はそのままに、アイテムを取得し直すこともなく、ListViewを復元する方法を記載します。

後述のソースコードについて

ListViewを使ってユーザ情報(UserListAdapterItem)を表示します。
今回の記事に関係ない以下の内容についてはソースコードに記載しておりません。

  • UserListAdapterItemの中身
  • ユーザ情報の一覧を表示するためのカスタムアダプター(UserListAdapter)のgetViewメソッド
  • ListViewのアイテムのレイアウトXML
  • UserListAdapterItemのリストの新規生成

ソースコード

ListViewActivity.java
/**
 * ListViewを表示しているActivity
 */
public class ListViewActivity extends AppCompatActivity {

    private ListView mUserListView;
    private UserListAdapter mUserListAdapter;

    /**
     * ListViewのアイテムをBundleに保存するためのキー
     */
    private static final String BUNDLE_KEY_ITEM_LIST = "item_list";

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list_view);

        // ListViewとそのAdapterの初期化
        mUserListView = (ListView) findViewById(R.id.list_user);
        mUserListAdapter = new UserListAdapter(this, new ArrayList<UserListAdapterItem>());
        mUserListView.setAdapter(mUserListAdapter);
    }

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

        // ListViewのアイテムを復元する
        if (savedInstanceState != null && !savedInstanceState.isEmpty()) {
            List<UserListAdapterItem> itemList = (List) savedInstanceState.getSerializable(BUNDLE_KEY_ITEM_LIST);
            mUserListAdapter.setItemList(itemList);
        }
    }

    @Override
    protected void onPostCreate(@Nullable Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);

        // Adapterが空だった場合はListViewに表示するアイテムを新規に取得する
        if (mUserListAdapter.isEmpty()) {
            List<UserListAdapterItem> itemList = createUserListAdapterItemList();
            mUserListAdapter.setItemList(itemList);
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        // 復元用にListViewのアイテムを保存する
        outState.putSerializable(BUNDLE_KEY_ITEM_LIST, mUserListAdapter.getItemList());
        super.onSaveInstanceState(outState);
    }

    /**
     * アイテムを生成する処理
     *
     * @return
     */
    private List<UserListAdapterItem> createUserListAdapterItemList() {
        // 記事に関係ないため省略
    }
}
activity_list_view.xml
<?xml version="1.0" encoding="utf-8"?>

<!-- ListViewActivityのレイアウト -->

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".view.activity.ListViewActivity">

    <ListView
        android:id="@+id/list_user"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>
UserListAdapter.java
/**
 * ListViewでユーザ情報(UserListAdapterItem)を表示するためのカスタムアダプター
 */
public class UserListAdapter extends ArrayAdapter<UserListAdapterItem> {

    private LayoutInflater mInflater;

    public UserListAdapter(Context context, List<UserListAdapterItem> objects) {
        super(context, 0, objects);

        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @NonNull
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // 記事に関係ないため省略
    }

    /**
     * Adapter内のアイテムをすべて取得する。
     * 返却する型がArrayListなのは、Serializableを継承しているため。
     *
     * @return
     */
    public ArrayList<UserListAdapterItem> getItemList() {
        ArrayList<UserListAdapterItem> itemList = new ArrayList<>();
        for (int i = 0, size = getCount(); i < size; i++) {
            UserListAdapterItem item = getItem(i);
            itemList.add(item);
        }
        return itemList;
    }

    /**
     * Adapterにアイテムのリストを設定する。
     *
     * @param itemList
     */
    public void setItemList(List<UserListAdapterItem> itemList) {
        clear();
        addAll(itemList);
    }

}

おわりに

上記のように実装いただければ、画面回転した時に、回転前に表示していたListViewの内容を復元することができます。
しかしこちらの方法では、Android 7 で重大な不具合が発生する可能性があります。
そのため、その解決策を 別の記事 で紹介したいと思います。

3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5