2014-10-09 53 views
2

現在,我確信這聽起來會讓很多人感到奇怪,但是我的ListView在旋轉我的設備時始終保持其位置。這並不是說這是一個特別糟糕的行爲(這是我最終的目標,當用戶旋轉他們的設備時記得ListView的位置),更重要的是似乎沒有原因爲什麼它正在保留的位置。我從來沒有告訴過它這樣做!即使當我嘗試強制更改ListView上的自定義適配器時,它也會更新(列表項)內的信息,但仍保留該元素的位置。在改變片段中的方向時總是保留ListView位置

經過進一步測試,如果我嘗試製作延遲Runnable(大約300ms延遲),我可以成功更改ArrayAdapter並將位置重置爲預期的頂部。

爲什麼在創建Fragment期間(在onCreateView,onActivityCreated等期間)強制ListView改變位置?

下面是一些代碼:

public class MainFragment extends Fragment { 
ListView list; 
ArrayList<String> skinslist; 
ArrayList<File> files; 
ArrayList<Integer> heights; 
File directory; 
String[] listitems; 
LinearLayout skin_list_error; 
SkinListAdapter adapter; 
SwipeRefreshLayout swipeLayout; 
View view; 

@Override 
public void onActivityCreated(Bundle savedInstanceState) { 
    super.onActivityCreated(savedInstanceState); 
    setHasOptionsMenu(true); 
    listitems = getResources().getStringArray(R.array.TestStrings); 
    list = (ListView) view.findViewById(R.id.skin_list); 
    skin_list_error = (LinearLayout) view.findViewById(R.id.skin_list_error); 

    //Initialize list items 
    if (isExternalStorageWritable() && isExternalStorageReadable()) { 
     directory = new File(Environment.getExternalStorageDirectory()); 
     //File directory = new File(getActivity().getFilesDir(), "Mine"); 
     directory.mkdir(); 
     CreateNoMediaFile.CreateNoMedia(directory); 
     File[] filedirectory = directory.listFiles(); 

     Arrays.sort(filedirectory, new Comparator<File>(){ 
      public int compare(File f1, File f2) 
      { 
       return Long.valueOf(f2.lastModified()).compareTo(f1.lastModified()); 
      } }); 

     skinslist = new ArrayList<String>(); 
     files = new ArrayList<File>(); 
     heights = new ArrayList<Integer>(); 
     for (File f : filedirectory) { 
      String filename = f.getName(); 
      if (filename.endsWith(".png")) { 
      skinslist.add(f.getName().substring(0, filename.length() - 4)); 
      files.add(f); 
      } 
     } 
     listitems = skinslist.toArray(new String[skinslist.size()]); 
      adapter = new SkinListAdapter(this.getActivity(), listitems, files, heights); 
      list.setAdapter(adapter); 
    } else { 
     Toast.makeText(getActivity(), "Error: Couldn't access phone storage", Toast.LENGTH_LONG).show(); 
     list.setVisibility(ListView.GONE); 
     skin_list_error.setVisibility(LinearLayout.VISIBLE); 
    } 
    //Finish initializing list items 

    swipeLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_container); 
    swipeLayout.setOnRefreshListener(new OnRefreshListener() { 

     @Override 
     public void onRefresh() { 
      refreshSkins(false); 
     } 

    }); 
    swipeLayout.setColorScheme(R.color.refresh_initial_color, 
      R.color.refresh_initial_color, 
      R.color.refresh_initial_color, 
      R.color.refresh_initial_color); 

} 

在此處,該視圖被充氣:

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    view = inflater.inflate(R.layout.skinlist, container, false); 
    return view; 
} 
+0

你在哪裏給'view'賦值?我想在'onCreateView()',你可以發佈它的代碼? – 2014-10-09 22:59:13

+0

當然!我只是將它添加到主帖子中。 – Michael 2014-10-09 23:07:29

+0

爲什麼從'onCreateView()'調用'super.onCreate()'? – 2014-10-09 23:11:34

回答

2

FragmentManager保存,並在其moveToState()方法載荷片段的視圖狀態。 (搜索saveFragmentViewState(f)f.restoreViewState())。

saveFragmentViewState()最終調用View.onSaveInstanceState()在層次結構中所有的意見,所以它可以節省ListView滾動位置,EditText內容等等。

更新:corresponding documentation(它是關於Activity,但Fragment生命週期由Activity生命週期導演):

然而,即使你什麼也不做,不實現的onSaveInstanceState(),一些活動狀態的恢復通過Activity類的onSaveInstanceState()的默認實現。具體而言,默認實現爲佈局中的每個視圖調用相應的onSaveInstanceState()方法,從而允許每個視圖提供有關應該保存的有關自身的信息。幾乎Android框架中的每個小部件都會根據需要實現此方法,以便在重新創建活動時自動保存並恢復UI的任何可見更改。例如,EditText小部件保存用戶輸入的任何文本,CheckBox小部件保存是否選中。您需要的唯一工作是爲要保存其狀態的每個窗口小部件提供唯一的ID(帶有android:id屬性)。如果一個小部件沒有ID,那麼系統不能保存它的狀態。

+0

非常感謝!我出人意料地從來沒有意識到,不要介意活動也是如此。 – Michael 2014-10-09 23:55:11

相關問題