

お世話になります  
Androidにて会社のアプリを開発しておりまして、  
fragmentを使い一覧ページを生成して、そこから詳細に遷移するなんていう感じのものを作っています

そこで、ちょっと一般的な質問なのですが、  
一覧から詳細に遷移後、また一覧に戻る際に、一覧ページでスクロールした位置に戻りたいのですが、fragmentのライフサイクルを見ると、popBackStackメソッドを使った場合  
また、onCreateViewから再生成になっているので、また、viewから作りなおしなので、これはもしかして、Activityを駆使するしかないのかなと思っているのですが、実際どうなのでしょうか？

参考までに現状のソースを載せます

[code]

    package jp.co.indival.shotalert.fragment;
    
                import android.app.Activity;
                import android.app.ProgressDialog;
                import android.os.Bundle;
                import android.support.v4.app.Fragment;
                import android.support.v4.app.FragmentTransaction;
                import android.support.v4.app.ListFragment;
                import android.util.Log;
                import android.view.LayoutInflater;
                import android.view.View;
                import android.view.ViewGroup;
    
                import android.widget.Button;
                import android.widget.ListView;
                import android.widget.TextView;
    
                import com.android.volley.Cache;
                import com.android.volley.DefaultRetryPolicy;
                import com.android.volley.Request;
                import com.android.volley.RequestQueue;
                import com.android.volley.Response;
                import com.android.volley.VolleyError;
                import com.android.volley.toolbox.JsonObjectRequest;
                import com.android.volley.toolbox.Volley;
                import com.costum.android.widget.PullAndLoadListView;
                import com.costum.android.widget.PullToRefreshListView;
                import com.google.android.gms.analytics.HitBuilders;
                import com.google.android.gms.analytics.Tracker;
    
                import org.apache.commons.lang3.StringUtils;
                import org.json.JSONArray;
                import org.json.JSONException;
                import org.json.JSONObject;
    
                import java.io.UnsupportedEncodingException;
                import java.util.ArrayList;
                import java.util.LinkedList;
                import java.util.List;
    
                import jp.co.indival.shotalert.R;
    
                import jp.co.indival.shotalert.adapter.WorkListAdapter;
                import jp.co.indival.shotalert.common.AppController;
                import jp.co.indival.shotalert.common.AppInfo;
                import jp.co.indival.shotalert.common.SearchCondition;
                import jp.co.indival.shotalert.common.Util;
    
    
                /**
                 * A fragment representing a list of Items.
                 * <p/>
                 * Large screen devices (such as tablets) are supported by replacing the ListView
                 * with a GridView.
                 * <p/>
                 * Activities containing this fragment MUST implement the {@link OnWorkInteractionListener}
                 * interface.
                 */
                public class WorkList extends ListFragment implements View.OnClickListener,PullToRefreshListView.OnRefreshListener{
    
    
                    // list with the data to show in the listview
                    private List<JSONObject> mListItems = new ArrayList<JSONObject>();
    
    
                    public static final String TAG = WorkList.class.getName();
    
                    public static final String shothost = AppInfo.getShotHost();
    
                    private OnWorkInteractionListener mListener;
    
                    /**
                     * The fragment's ListView/GridView.
                     */
                    private PullAndLoadListView mListView;
    
                    private TextView totalView;
    
                    private int totalCount = 0;
                    private int start = 0;
                    private int size = 20;
                    private int loadmax = 100;//100件以上はロードさせない
    
                    private Boolean loadmore = false;
                    private Boolean initload = false;
                    private SearchCondition cond;
                    private List<String> tagAry = new ArrayList<String>();
    
                    private boolean fragmentactive = false;
    
    
                    /**
                     * The Adapter which will be used to populate the ListView/GridView with
                     * Views.
                     */
                    private WorkListAdapter mAdapter;
    
                    // TODO: Rename and change types of parameters
                    public static WorkList newInstance() {
                        WorkList fragment = new WorkList();
                        return fragment;
                    }
    
                    /**
                     * Mandatory empty constructor for the fragment manager to instantiate the
                     * fragment (e.g. upon screen orientation changes).
                     */
                    public WorkList() {
                    }
    
    
    
                    @Override
                    public void onCreate(Bundle savedInstanceState) {
                        super.onCreate(savedInstanceState);
                        fragmentactive = true;
    
    
                    }
    
                    @Override
                    public void onStart() {
                        super.onStart();
                        loadmore = false;
                        start = 0;
                        Tracker tracker = ((AppController)getActivity().getApplication()).getTracker();
                        tracker.setScreenName("WorkList");
                        tracker.send(new HitBuilders.AppViewBuilder().build());
                    }
    
                    /**
                     *  検索用のパラメータ作成
                     */
                    private String _setParameter() {
    
                        List<String> paramAry = new ArrayList<String>();
    
    
    
                        if(cond.getCodeArea() != null){
                            paramAry.add("a="+cond.getCodeArea());
                        }
                        if(cond.getCodeStartday() != null){
                            paramAry.add("startdate="+cond.getCodeStartday());
                        }
                        if(cond.getCodePref() != null && cond.getCodePref() != ""){
                            paramAry.add("prefcode="+cond.getCodePref());
                            paramAry.add("largeareacode=L-0"+cond.getCodePref());
                        }
                        if(cond.getCodeMinimumday() != null){
                            paramAry.add("minimumday="+cond.getCodeMinimumday());
                        }
                        if(cond.getCodeMainjob() != null){
                            paramAry.add("mainjobcode="+cond.getCodeMainjob());
                        }
                        if(cond.getCodeOptionTag() != null){
                            paramAry.add("tags="+cond.getCodeOptionTag());
                        }
    
                        if(cond.getCodeHibarai() != null
                                && cond.getCodeHibarai() != ""
                                && !tagAry.contains(cond.getCodeHibarai())
                                ){
                            tagAry.add(cond.getCodeHibarai());
                        }
    
                        if(cond.getCodeNoInterview() != null
                                && cond.getCodeNoInterview() != ""
                                && !tagAry.contains(cond.getCodeNoInterview())
                                ){
                            tagAry.add(cond.getCodeNoInterview());
                        }
    
                        if(cond.getCodeDayoff() != null
                                && cond.getCodeDayoff() != ""
                                && !tagAry.contains(cond.getCodeDayoff())
                                ){
                            tagAry.add(cond.getCodeDayoff());
                        }
    
                        if(cond.getCodeStudentok() != null
                                && cond.getCodeStudentok() != ""
                                && !tagAry.contains(cond.getCodeStudentok())
                                ){
                            tagAry.add(cond.getCodeStudentok());
                        }
    
    
                        if(cond.getCodeShuhu() != null
                                && cond.getCodeShuhu() != ""
                                && !tagAry.contains(cond.getCodeShuhu())
                                ){
                            tagAry.add(cond.getCodeShuhu());
                        }
    
                        if(cond.getCodeBeginer() != null
                                && cond.getCodeBeginer() != ""
                                && !tagAry.contains(cond.getCodeBeginer())
                                ){
                            tagAry.add(cond.getCodeBeginer());
                        }
    
                        paramAry.add("start="+String.valueOf(start));
                        paramAry.add("results="+String.valueOf(size));
                        paramAry.add("output=json");
                        paramAry.add("apliflag=1");
                        paramAry.add("key_api=key_001");
    
                        if(tagAry.size() > 0){
    
                            String[] array = (String[])tagAry.toArray(new String[0]);
                            String tagstr = StringUtils.join(array, ",");
                            paramAry.add("tags[]="+tagstr);
                        }
    
                        String[] array = (String[])paramAry.toArray(new String[0]);
    
                        return StringUtils.join(array,"&");
    
                    }
    
                    @Override
                    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                             Bundle savedInstanceState) {
                        Log.d("WorkList","===========================================");
                        Log.d("WorkList","onCreateView");
                        Log.d("WorkList","===========================================");
    
                        View view = inflater.inflate(R.layout.fragment_worklist, container, false);
    
                        cond = SearchCondition.newInstance(getActivity());
                        initload = true;
                        start = 0;
    
                        mListItems = new LinkedList<JSONObject>();
    
    
                        totalView = (TextView) view.findViewById(R.id.total);
    
                        Button resetbtn = (Button) view.findViewById(R.id.resetbtn);
                        resetbtn.setOnClickListener(this);
    
                        // Set the adapter
                        mListView = (PullAndLoadListView) view.findViewById(android.R.id.list);
    
                        //更新と、moreのアクションを登録
                        mListView.setOnRefreshListener(this);
    
                        mListView.setOnLoadMoreListener(new PullAndLoadListView.OnLoadMoreListener() {
    
                            public void onLoadMore() {
    
                                loadmore = true;
                                // コンテンツが追加される前に呼ばれることもある
                                if(mAdapter == null){
                                    return;
                                }
    
                                // Do the work to load more items at the end of list
                                // here
                                //totalが開始点を超えてない場合だけ、次をロードする
                                if(totalCount > start+size){
                                    start = start+size;
                                    String param = _setParameter();
                                    String loadurl = shothost+"sw/app/work?"+param;
                                    _getDataByVolley(loadurl);
                                }else{
                                    //((PullAndLoadListView) getListView()).onLoadMoreComplete();
                                }
    
                            }
                        });
    
    
                        // Set OnItemClickListener so we can be notified on item clicks
    
                        return view;
                    }
    
                    @Override
                    public void onActivityCreated (Bundle savedInstanceState){
                        super.onActivityCreated(savedInstanceState);
    
                        start++;
                        //Log.d("URL","http://dev.swallow.cu01.shotlabo.info/sw/app/work?md=2&wd=2015-02-21&a=01&wtk=1&wdf=2015-02-19&key_api=key_001&output=json&start="+start+"&results="+size+"&apliflag=1");
    
                        String param = _setParameter();
    
                        Log.d("URL",shothost+"sw/app/work?"+param);
                        _getDataByVolley(shothost+"sw/app/work?"+param);
                    }
    
    
                    private void _loadData(String url){
    
                        String tag_json_arry = "json_array_req";
    
                        final ProgressDialog pDialog = new ProgressDialog(getActivity());
                        pDialog.setMessage("Loading...");
                        pDialog.show();
    
                        JsonObjectRequest jsonObjReq =new JsonObjectRequest(
                                // HTTPメソッド名を設定する。GETかPOSTか等
                                Request.Method.GET
                                // リクエスト先のURLを設定する
                                ,url
                                // リクエストパラメーターを設定する
                                ,(String)null
                                // 通信成功時のリスナーを設定する
                                ,new Response.Listener<JSONObject>() {
                                    @Override
                                    public void onResponse(JSONObject response) {
                                        // 通信成功時の処理
                                        try {
                                            _parseJson(response);
                                        } catch (JSONException e) {
                                            e.printStackTrace();
                                        }
                                        pDialog.dismiss();
                                    }
    
    
                                }
                                // 通信失敗時のリスナーを設定する
                                ,new Response.ErrorListener() {
                                    @Override
                                    public void onErrorResponse(VolleyError error) {
                                        // 通信失敗時の処理
                                        pDialog.dismiss();
                                    }
                                }
                        );
                        int custom_timeout_ms = 10000;
                        DefaultRetryPolicy pol = new DefaultRetryPolicy(custom_timeout_ms,
                                DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
                                DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
                        jsonObjReq.setRetryPolicy(pol);
    
                        // Adding request to request queue
                        AppController.getInstance(getActivity()).addToRequestQueue(jsonObjReq, tag_json_arry);
    
                    }
    
                    /**
                     * _getDataFromCafhe
                     * volleyは通信すると自動でキャッシュに入れる（入れるとことを拒否もできるが）
                     * なので、キャッシュからデータを取得
                     * @access private
                     *
                     *
                     */
                    private void _getDataByVolley(String url){
                        Log.d("URL",url);
                        //まずはキャッシュを確認。なければ、volleyで通信
                        Cache cache = AppController.getInstance(getActivity()).getRequestQueue().getCache();
                        Cache.Entry entry = cache.get(url);
                        if(entry != null){
                            try {
                                String data = new String(entry.data, "UTF-8");
                                JSONObject workJson = new JSONObject(data);
                                _parseJson(workJson);
    
                                // handle data, like converting it to xml, json, bitmap etc.,
                            } catch (UnsupportedEncodingException e) {
                                e.printStackTrace();
                                Log.e(TAG,e.toString());
    
                            } catch (JSONException e) {
                                e.printStackTrace();
                                Log.e(TAG,e.toString());
                            }
    
                        }else{
                            // Cached response doesn't exists. Make network call here
                            _loadData(url);
                        }
                    }
    
    
                    /**
                     * _parseJson
                     * Jsonのパース
                     *
                     * @param workJson
                     */
                    private void _parseJson(JSONObject workJson) throws JSONException {
                        JSONObject resultSet = workJson.getJSONObject("ResultSet");
    
                        if(!loadmore) {
                            _displayList(resultSet, workJson);
                        }else{
                            _moreList(workJson);
                        }
                    }
    
                    /**
                     * more用のデータセット
                     * @param workJson
                     */
                    private void _moreList(JSONObject workJson) {
                        _setListData(workJson);
    
                        // We need notify the adapter that the data have been changed
                        mAdapter.notifyDataSetChanged();
    
                        // Call onLoadMoreComplete when the LoadMore task, has finished
                        ((PullAndLoadListView) getListView()).onLoadMoreComplete();
    
                        //マックスまで達したらloadmoreリスナーは削除
                        if(totalCount <= start+size || start+size >= loadmax){
                            mListView.setOnLoadMoreListener(null);
                        }
    
    
                    }
    
    
                    /**
                     * リスト表示
                     * @param resultSet
                     * @param workJson
                     */
                    private void _displayList(JSONObject resultSet, JSONObject workJson){
                        String totalStr = resultSet.optString("totalResultsAvailable");
                        if(totalStr != null){
                            totalCount = Integer.parseInt(totalStr);
                        }
    
                        if(totalCount == 0 && !loadmore){
                            setEmptyText("");
                        }
    
                        totalView.setText("検索結果:"+totalStr+"件");
    
                        _setListData(workJson);
    
                        //set adapter
                        mAdapter = new WorkListAdapter(getActivity(),R.layout.worklist_row,mListItems);
                        mListView.setAdapter(mAdapter);
    
                        int listsize = mAdapter.getCount();
                        if(listsize < 4){
                            mListView.mRefreshView.setMinimumHeight(0);
                            mListView.mRefreshView.setVisibility(View.GONE);
                            mListView.mRefreshViewText.setVisibility(View.GONE);
    
                            ViewGroup.LayoutParams lp = mListView.mRefreshViewProgress.getLayoutParams();
                            ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams)lp;
                            mlp.setMargins(0,0,0,0);
    
                            mListView.mRefreshViewProgress.setLayoutParams(mlp);
                            mListView.mRefreshViewText.setLayoutParams(mlp);
                            mListView.mRefreshView.setPadding(0, 0, 0, 0);
    
                        }
    
                        if(!initload){
                            ((PullAndLoadListView) getListView()).onRefreshComplete();
                        }else{
                            initload = false;
                        }
    
                        //20件以下なら次は読み込まない
                        if(totalCount <= size){
                            mListView.setOnLoadMoreListener(null);
                        }
    
    
    
                    }
    
                    /**
                     *
                     * @param workJson
                     */
                    private void _setListData(JSONObject workJson){
                        JSONArray jsonAry = workJson.optJSONArray("Result");
    
                        for (int i = 0; i < jsonAry.length(); i++) {
                            JSONObject json = jsonAry.optJSONObject(i);
                            mListItems.add(json);
                        }
                    }
    
    
                    @Override
                    public void onAttach(Activity activity) {
                        super.onAttach(activity);
                        try {
                            mListener = (OnWorkInteractionListener) activity;
                        } catch (ClassCastException e) {
                            throw new ClassCastException(activity.toString()
                                    + " must implement OnFragmentInteractionListener");
                        }
                    }
    
                    @Override
                    public void onDetach() {
                        super.onDetach();
                        mListener = null;
                    }
    
    
                    @Override
                    public void onListItemClick(ListView l, View view, int position, long id) {
                        String workid = mListItems.get(position-1).optString("WorkId");
                //        if (null != mListener) {
                //            // Notify the active callbacks interface (the activity, if the
                //            // fragment is attached to one) that an item has been selected.
                //            String workid = mListItems.get(position-1).optString("WorkId");
                //            mListener.onWorkInteraction(workid);
                //        }
    
                        // フラグメントのインスタンスを生成する。
                        Fragment newFragment = Web.newInstance();
                        FragmentTransaction ft = getFragmentManager().beginTransaction();
    
                        // ↓アクション指定
                        ft.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left);
    
                        // Layout位置先の指定
                        ft.replace(R.id.container, newFragment);
    
                        Bundle bundle = new Bundle();
                        bundle.putString("url",shothost+"sw/detail/"+workid+"?mc=04");
                        Log.d("DETAIL",shothost+"sw/detail/"+workid+"?mc=04");
                // フラグメントに渡す値をセット
                        newFragment.setArguments(bundle);
                        ft.addToBackStack("worklist");
                        ft.commit();
                    }
    
                    /**
                     * The default content for this Fragment has a TextView that is shown when
                     * the list is empty. If you would like to change the text, call this method
                     * to supply the text it should use.
                     */
                    public void setEmptyText(CharSequence emptyText) {
                        View emptyView = mListView.getEmptyView();
    
                        if (emptyView instanceof TextView) {
                            ((TextView) emptyView).setText("条件に該当するワークは見つかりませんでした");
                        }
                    }
    
                    @Override
                    public void onClick(View v) {
                        if (null != mListener) {
                            // Notify the active callbacks interface (the activity, if the
                            // fragment is attached to one) that an item has been selected.
                            mListener.onResetCondition();
                        }
                    }
    
                    @Override
                    public void onRefresh() {
                        loadmore = false;
                        start = 0;
                        mListItems = new ArrayList<JSONObject>();
                        start++;
    
                        String param = _setParameter();
                        String loadurl = shothost+"sw/app/work?"+param;
                        _getDataByVolley(loadurl);
                    }
    
                    /**
                     * This interface must be implemented by activities that contain this
                     * fragment to allow an interaction in this fragment to be communicated
                     * to the activity and potentially other fragments contained in that
                     * activity.
                     * <p/>
                     * See the Android Training lesson <a href=
                     * "http://developer.android.com/training/basics/fragments/communicating.html"
                     * >Communicating with Other Fragments</a> for more information.
                     */
                    public interface OnWorkInteractionListener {
                        // TODO: Update argument type and name
                        public void onWorkInteraction(String workid);
                        public void onResetCondition();
                    }
    
    
    
    
                }
    
[/code]

ご教授お願いします


CC BY-SA 3.0
2015-04-22T10:13:23.177
9453
2016-03-18T17:37:52.473
403
question
android fragment android-activity
Androidのfragmentを使った一覧ページから詳細ページへ遷移し、その後戻る場合の処理


R.id.container が FrameLayout で、詳細ページの背景が十分に不透明なら単純に

[code]

    ft.add(R.id.container, newFragment);
    
[/code]

で、いけるような気がしますが、どうなんでしょう。

replace でなければいけないのなら、onDestroyView 内でスクロール情報（例えばリストの firstVisiblePosition など）を
Arguments に追加しておくとかですかね。これはビュー再生成の前後でリストの内容が同一でないと厳しいかもしれません。

というか replace による再生成は基本 onCreateView からっぽいんで、その前の onCreate
でリストビューを作ってフィールドに保持しておいて onCreateView でくっつけるようにしておけばいいようにも思います。


CC BY-SA 3.0
2015-04-23T09:36:22.873
9511
2015-04-23T09:50:36.790
2015-04-23T09:50:36.790
7558
7558
9453
answer