2014-10-09 54 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

相关问题