现在,我确信这对许多人来说听起来很奇怪,但是我的ListView在旋转设备时始终保持其位置有问题。并不是说这是一个特别糟糕的行为(这是我最终的目标,让它在用户旋转设备时记住ListView的位置),更是如此,似乎没有理由为什么< / em>它保留了这个位置。我从来没有告诉它这样做!即使我尝试在ListView上强制更改自定义适配器,它也会更新内部信息(列表项)但仍保留元素的位置。
经过进一步的测试,如果我尝试制作延迟的Runnable(大约300ms延迟),我可以成功更改ArrayAdapter,并且位置会按预期重置到顶部。
为什么在创建片段期间强制ListView改变位置(在onCreateView,onActivityCreated等期间)?
以下是一些代码:
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 :(得分:2)
FragmentManager
在其moveToState()方法中保存并加载片段的视图状态。 (搜索saveFragmentViewState(f)
和f.restoreViewState()
)。
saveFragmentViewState()
最终会针对层次结构中的所有视图调用View.onSaveInstanceState()
,因此会保存ListView
滚动位置,EditText
内容以及更多内容。
更新:corresponding documentation(关于Activity
,但Fragment
生命周期由Activity
生命周期定向):
但是,即使您不执行任何操作并且未实现onSaveInstanceState(),Activity类的默认实现onSaveInstanceState()也会恢复某些活动状态。具体来说,默认实现为布局中的每个View调用相应的onSaveInstanceState()方法,这允许每个视图提供有关应保存的自身的信息。几乎Android框架中的每个窗口小部件都会适当地实现此方法,以便在重新创建活动时自动保存和恢复对UI的任何可见更改。例如,EditText小部件保存用户输入的任何文本,CheckBox小部件保存是否已选中。您需要的唯一工作是为要保存其状态的每个小部件提供唯一的ID(带有android:id属性)。如果窗口小部件没有ID,则系统无法保存其状态。