我一直试图搜索这个问题,但我找不到任何解决方案。我在片段中保存 ListView 项目时遇到问题。情况是我有几个片段
假设 FRAGMENT A、FRAGMENT B 和 FRAGMENT C,并且 FRAGMENT A 有一个列表视图,列表视图的项目可以在用户滚动时更改(就像社交媒体应用程序中的时间线一样)。当我更改片段 A 时,我使用了 addToBackStack(null) 方法。
问题是,如果按下后退按钮,如何保存列表视图并恢复其?
onSaveInstanceState() 永远不会被调用,因为 Activity 主机永远不会被杀死,只使用以下方法更改片段:
public void changeFragment(Fragment fragment, ColorDrawable colorDrawable){
Fragment newFrag = fragment;
ColorDrawable newColor = colorDrawable;
String backStateName = fragment.getClass().getName();
FragmentManager manager = getSupportFragmentManager();
boolean fragmentPopped = manager.popBackStackImmediate (backStateName, 0);
if (!fragmentPopped){ //fragment not in back stack, create it.
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content_fragment, fragment);
ft.addToBackStack(backStateName);
ft.commit();
}
//to change the actionbar color
getSupportActionBar().setBackgroundDrawable(newColor);
}
这是我尝试保存和恢复列表视图的代码:
@Override
public void onDestroyView() {
super.onDestroyView();
//try to save listview scroll
index = myList.getFirstVisiblePosition();
View v = myList.getChildAt(0);
top = (v == null) ? 0 : (v.getTop() - myList.getPaddingTop());
index = 1;
//try to save listview items
savedAdapter = adapter;
fromBackStack = true;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
myList.setSelectionFromTop(index, top);
myList.setAdapter(savedAdapter);
}
这是我到目前为止所做的代码:
package com.ngapainya.ngapainya.fragment;
import android.app.Activity;
import android.graphics.drawable.ColorDrawable;
import android.net.ParseException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ListView;
import com.ngapainya.ngapainya.R;
import com.ngapainya.ngapainya.activity.volunteer.ContainerActivity;
import com.ngapainya.ngapainya.adapter.HomeAdapter;
import com.ngapainya.ngapainya.fragment.child.DetailPostFragment;
import com.ngapainya.ngapainya.model.Home;
import java.util.ArrayList;
/**
* A simple {@link Fragment} subclass.
*/
public class HomeFragment extends Fragment implements AdapterView.OnItemClickListener, SwipeRefreshLayout.OnRefreshListener{
private FragmentActivity myContext;
private View myFragmentView;
private ArrayList<Home> filelist;
private ListView myList;
private HomeAdapter adapter;
private SwipeRefreshLayout swipeRefreshLayout;
//try save instance listview
boolean fromBackStack = false;
int index;
int top;
HomeAdapter savedAdapter;
@Override
public void onDestroyView() {
super.onDestroyView();
//try to save listview scroll
index = myList.getFirstVisiblePosition();
View v = myList.getChildAt(0);
top = (v == null) ? 0 : (v.getTop() - myList.getPaddingTop());
index = 1;
//try to save listview items
savedAdapter = adapter;
fromBackStack = true;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
myList.setSelectionFromTop(index, top);
myList.setAdapter(savedAdapter);
}
@Override
public void onAttach(Activity activity) {
myContext = (FragmentActivity) activity;
super.onAttach(activity);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
myFragmentView = inflater.inflate(R.layout.fragment_home, container, false);
filelist = new ArrayList<Home>();
//dummy data
filelist.add(new Home("post", 1)); //post image
filelist.add(new Home("post", 2)); //post location
filelist.add(new Home("post", 3)); //post url
filelist.add(new Home("post", 4)); //become friend with
filelist.add(new Home("post", 0)); //post status
swipeRefreshLayout = (SwipeRefreshLayout) myFragmentView.findViewById(R.id.swipe_refresh_layout);
swipeRefreshLayout.setOnRefreshListener(this);
/**
* Showing Swipe Refresh animation on activity create
* As animation won't start on onCreate, post runnable is used
*/
swipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
swipeRefreshLayout.setRefreshing(true);
//do something
swipeRefreshLayout.setRefreshing(false);
}
}
);
myList = (ListView) myFragmentView.findViewById(R.id.list_home);
//myList.setAdapter(new HomeAdapter(myContext, filelist));
adapter = new HomeAdapter(myContext, filelist);
myList.setOnItemClickListener(this);
if(!fromBackStack) {
new RemoteDataTask().execute();
}
return myFragmentView;
}
/**
* This method is called when swipe refresh is pulled down
*/
@Override
public void onRefresh() {
//do something
myList.setAdapter(adapter);
ArrayList<Home> new_filelist = new ArrayList<>();
new_filelist.add(new Home("Post", 4));
filelist.addAll(0, new_filelist);
adapter.notifyDataSetChanged();
swipeRefreshLayout.setRefreshing(false);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Home tmp = (Home) parent.getItemAtPosition(position);
DetailPostFragment detailPostFragment = new DetailPostFragment();
Bundle args = new Bundle();
switch (tmp.type) {
case 0:
args.putInt("postType", tmp.type);
detailPostFragment.setArguments(args);
((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
break;
case 1:
args.putInt("postType", tmp.type);
detailPostFragment.setArguments(args);
((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
break;
case 2:
args.putInt("postType", tmp.type);
detailPostFragment.setArguments(args);
((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
break;
case 3:
args.putInt("postType", tmp.type);
detailPostFragment.setArguments(args);
((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
break;
case 4:
args.putInt("postType", tmp.type);
detailPostFragment.setArguments(args);
((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
break;
}
}
private class RemoteDataTask extends AsyncTask<String, Void, ArrayList<Home>> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected ArrayList<Home> doInBackground(String... urls) {
try {
ArrayList<Home> new_filelist = new ArrayList<Home>();
new_filelist.add(new Home("post", 3)); //post url
new_filelist.add(new Home("post", 4)); //become friend with
new_filelist.add(new Home("post", 0)); //post status
filelist.addAll(new_filelist);
} catch (ParseException e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return filelist;
}
@Override
protected void onPostExecute(ArrayList<Home> organization) {
myList.setAdapter(new HomeAdapter(myContext, filelist));
// Create an OnScrollListener
myList.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view,
int scrollState) { // TODO Auto-generated method stub
int threshold = 1;
int count = myList.getCount();
if (scrollState == SCROLL_STATE_IDLE) {
if (myList.getLastVisiblePosition() >= count
- threshold) {
// Execute LoadMoreDataTask AsyncTask
new LoadMoreDataTask().execute();
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
}
});
}
}
public class LoadMoreDataTask extends AsyncTask<String, Void, ArrayList<Home>> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected ArrayList<Home> doInBackground(String... urls) {
try {
// web service request
ArrayList<Home> new_filelist = new ArrayList<Home>();
new_filelist.add(new Home("post", 0)); //post status
if(new_filelist != null && new_filelist.size() > 0 ){
filelist.addAll(new_filelist);
}
} catch (Exception e) {
e.printStackTrace();
}
return filelist;
}
@Override
protected void onPostExecute(ArrayList<Home> organization) {
int position = myList.getLastVisiblePosition();
adapter = new HomeAdapter(myContext, filelist);
myList.setAdapter(adapter);
adapter.notifyDataSetChanged();
myList.setSelectionFromTop(position, 0);
}
}
}
我希望有人可以帮助我,谢谢。
更新的代码 这是我目前的代码,当我尝试保存列表视图项及其适配器时它可以工作,也许这有点棘手。如果有人有任何想法,将不胜感激。
package com.ngapainya.ngapainya.fragment;
import android.app.Activity;
import android.graphics.drawable.ColorDrawable;
import android.net.ParseException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ListView;
import com.ngapainya.ngapainya.R;
import com.ngapainya.ngapainya.activity.volunteer.ContainerActivity;
import com.ngapainya.ngapainya.adapter.HomeAdapter;
import com.ngapainya.ngapainya.fragment.child.DetailPostFragment;
import com.ngapainya.ngapainya.model.Home;
import java.util.ArrayList;
/**
* A simple {@link Fragment} subclass.
*/
public class HomeFragment extends Fragment implements AdapterView.OnItemClickListener, SwipeRefreshLayout.OnRefreshListener{
private FragmentActivity myContext;
private View myFragmentView;
private ArrayList<Home> filelist;
private ListView myList;
private HomeAdapter adapter;
private SwipeRefreshLayout swipeRefreshLayout;
/*
* these variables used to restore the listview
* when calling the fragment from backstack
* */
private boolean fromBackStack = false;
private HomeAdapter savedAdapter;
private ArrayList<Home> savedFilelist;
@Override
public void onDestroyView() {
super.onDestroyView();
savedAdapter = adapter;
savedFilelist = filelist;
fromBackStack = true;
Log.e("onDestroyView", "onDestroyView");
}
@Override
public void onAttach(Activity activity) {
myContext = (FragmentActivity) activity;
super.onAttach(activity);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
myFragmentView = inflater.inflate(R.layout.fragment_home, container, false);
Log.e("onCreateView", "onCreateView");
swipeRefreshLayout = (SwipeRefreshLayout) myFragmentView.findViewById(R.id.swipe_refresh_layout);
swipeRefreshLayout.setOnRefreshListener(this);
/**
* Showing Swipe Refresh animation on activity create
* As animation won't start on onCreate, post runnable is used
*/
/*swipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
swipeRefreshLayout.setRefreshing(true);
//do something
swipeRefreshLayout.setRefreshing(false);
}
}
);*/
myList = (ListView) myFragmentView.findViewById(R.id.list_home);
//myList.setAdapter(new HomeAdapter(myContext, filelist));
myList.setOnItemClickListener(this);
filelist = new ArrayList<Home>();
adapter = new HomeAdapter(myContext, filelist);
if(fromBackStack) {
filelist = savedFilelist;
adapter = savedAdapter;
}
new RemoteDataTask().execute();
return myFragmentView;
}
/**
* This method is called when swipe refresh is pulled down
*/
@Override
public void onRefresh() {
ArrayList<Home> new_filelist = new ArrayList<>();
new_filelist.add(new Home("Post", 4));
filelist.addAll(0, new_filelist);
adapter.notifyDataSetChanged();
swipeRefreshLayout.setRefreshing(false);
Log.e("onRefresh", "onRefresh");
}
/*
* This method is called whenever the listview item is clicked
* */
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Home tmp = (Home) parent.getItemAtPosition(position);
DetailPostFragment detailPostFragment = new DetailPostFragment();
Bundle args = new Bundle();
switch (tmp.type) {
case 0:
args.putInt("postType", tmp.type);
detailPostFragment.setArguments(args);
((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
break;
case 1:
args.putInt("postType", tmp.type);
detailPostFragment.setArguments(args);
((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
break;
case 2:
args.putInt("postType", tmp.type);
detailPostFragment.setArguments(args);
((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
break;
case 3:
args.putInt("postType", tmp.type);
detailPostFragment.setArguments(args);
((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
break;
case 4:
args.putInt("postType", tmp.type);
detailPostFragment.setArguments(args);
((ContainerActivity) getActivity()).changeFragment(detailPostFragment, new ColorDrawable(getResources().getColor(R.color.ColorPrimary)));
break;
}
}
/*
* This method is called in onCreateView method
* Used to load data from server and populate them into
* the listview
* */
private class RemoteDataTask extends AsyncTask<String, Void, ArrayList<Home>> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected ArrayList<Home> doInBackground(String... urls) {
try {
ArrayList<Home> new_filelist = new ArrayList<Home>();
//dummy data
new_filelist.add(new Home("post", 1)); //post image
new_filelist.add(new Home("post", 2)); //post location
new_filelist.add(new Home("post", 3)); //post url
new_filelist.add(new Home("post", 4)); //become friend with
new_filelist.add(new Home("post", 0)); //post status
new_filelist.add(new Home("post", 3)); //post url
new_filelist.add(new Home("post", 4)); //become friend with
new_filelist.add(new Home("post", 0)); //post status
filelist.addAll(new_filelist);
} catch (ParseException e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return filelist;
}
@Override
protected void onPostExecute(ArrayList<Home> organization) {
myList.setAdapter(adapter);
// Create an OnScrollListener
myList.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view,
int scrollState) { // TODO Auto-generated method stub
int threshold = 1;
int count = myList.getCount();
if (scrollState == SCROLL_STATE_IDLE) {
if (myList.getLastVisiblePosition() >= count
- threshold) {
// Execute LoadMoreDataTask AsyncTask
new LoadMoreDataTask().execute();
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
}
});
}
}
/*
* This method is called when the listview pulled down
* it will trigger this method to load more items from server
* */
public class LoadMoreDataTask extends AsyncTask<String, Void, ArrayList<Home>> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected ArrayList<Home> doInBackground(String... urls) {
try {
// web service request
ArrayList<Home> new_filelist = new ArrayList<Home>();
new_filelist.add(new Home("post", 0)); //post status
new_filelist.add(new Home("post", 1));
if(new_filelist != null && new_filelist.size() > 0 ){
filelist.addAll(new_filelist);
}
} catch (Exception e) {
e.printStackTrace();
}
return filelist;
}
@Override
protected void onPostExecute(ArrayList<Home> organization) {
int position = myList.getLastVisiblePosition();
//adapter = new HomeAdapter(myContext, filelist);
myList.setAdapter(adapter);
adapter.notifyDataSetChanged();
myList.setSelectionFromTop(position, 0);
}
}
}