我有一个由MainActivity托管的PhotosFrgament类,带有一个tablayout。 PhotoFragment允许用户从自定义图库中选择多张照片并将其显示在ListView中。但是在屏幕旋转时,会清除PhotosFragment。根据我的理解,我应该使用setRetainInstance(true),但它似乎不起作用,任何想法?
public class MainActivity extends AppCompatActivity {
private TabLayout tabLayout;
private ViewPager viewPager;
private static int TAB_ITEMS=1;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set a Toolbar to replace the ActionBar.
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
setTitle(R.string.photos);
tabLayout = (TabLayout)findViewById(R.id.tabs);
viewPager = (ViewPager)findViewById(R.id.viewpager);
/**
*Set an Apater for the View Pager
*/
viewPager.setAdapter(new MyAdapter(getSupportFragmentManager()));
/**
* Now , this is a workaround ,
* The setupWithViewPager dose't works without the runnable .
* Maybe a Support Library Bug .
*/
tabLayout.post(new Runnable() {
@Override
public void run() {
tabLayout.setupWithViewPager(viewPager);
}
});
//check for parent activity defined in the manifest before
//displaying caret
if(NavUtils.getParentActivityName(this) != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}//end method onCreate
class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
/**
* Return fragment with respect to Position .
*/
@Override
public Fragment getItem(int position)
{
switch (position){
case 0 :
return new Photos();
}
return null;
}
@Override
public int getCount() {
return TAB_ITEMS;
}
/**
* This method returns the title of the tab according to the position.
*/
@Override
public CharSequence getPageTitle(int position) {
switch (position){
case 0 :
return "Photos";
}
return null;
}
}//end class MyAdapter
@Override
public boolean onOptionsItemSelected(MenuItem item){
switch(item.getItemId()){
case android.R.id.home:
//if there is a parent activity declared in the manifest
//then navigate to the parent activity
if(NavUtils.getParentActivityName(this) != null)
NavUtils.navigateUpFromSameTask(this);
return true;
default:
return super.onOptionsItemSelected(item);//implement superclass
//implementation
}
}//end method onOptionsItemSelected
}//end class MainActivity
public class PhotosFragment extends ListFragment {
private static final int SELECT_MULTIPLE_PHOTOS = 0;//Set Intent Id
public static final String CustomGalleryIntentKey = "ImageArray";//Set Intent Key Value
private static final String TAG = "PhotosFragment";
private EditText mImagesDescriptionEditText;
private RelativeLayout mImagesDescriptionRelativeLayout;
private ListView mSelectedImagesListView;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setRetainInstance(true);//retain fragment on configuration changes
setHasOptionsMenu(true);//fragment will be implementing menu call backs
//on behalf of activity
}//end method onCreate
@Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
setRetainInstance(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent
,Bundle savedInstanceState){
View v = inflater.inflate(R.layout.fragment_photos, parent,false);
mSelectedImagesListView = (ListView)v.findViewById(android.R.id.list);
mImagesDescriptionRelativeLayout = (RelativeLayout)
v.findViewById(R.id.photos_descriptionRelativeLayout);
mImagesDescriptionEditText = (EditText)v.findViewById(R.id.photos_descriptionEditText);
mImagesDescriptionRelativeLayout.setVisibility(View.INVISIBLE);
return v;
}//end method onCreateView
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
super.onCreateOptionsMenu(menu,inflater);
inflater.inflate(R.menu.fragment_photos, menu);
}//end method onCreateOptionsMenu
@Override
public boolean onOptionsItemSelected(MenuItem item){
switch(item.getItemId()){
case R.id.menu_item_upload_photo:
//Start Custom Gallery Activity by passing intent id
Intent i = new Intent(getActivity(),CustomGalleryActivity.class);
startActivityForResult(i,SELECT_MULTIPLE_PHOTOS);
return true;
default:
return super.onOptionsItemSelected(item);
}//end switch
}//end onOptionsItemSelected
@Override
public void onActivityResult(int requestCode, int resultCode,
Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode != Activity.RESULT_OK)
return;
if(requestCode == SELECT_MULTIPLE_PHOTOS){
String imagesArray = data.getStringExtra(CustomGalleryIntentKey);//get Intent data
//Convert string array into List by splitting by ',' and substring after '[' and before ']'
List<String> selectedImages = Arrays.asList(imagesArray.substring(1, imagesArray.length() - 1).split(", "));
loadSelectedImagesListView(new ArrayList<String>(selectedImages));
}
}
private void loadSelectedImagesListView(ArrayList<String> imagesArray){
try{
mImagesDescriptionRelativeLayout.setVisibility(View.VISIBLE);
}catch (Throwable e){
e.printStackTrace();
}
SelectedImagesAdapter adapter = new SelectedImagesAdapter(imagesArray);
mSelectedImagesListView.setAdapter(adapter);
}
//custom adapter as inner class
private class SelectedImagesAdapter extends ArrayAdapter<String>{
public SelectedImagesAdapter(ArrayList<String> imagesArray){
super(getActivity(),0,imagesArray);
}
@Override
public View getView(int position, View convertView, ViewGroup parent){
//if we arent given a view inflate one
//if there's no recycled view passed in inflate one
if(convertView == null)
convertView = getActivity()
.getLayoutInflater()
.inflate(R.layout.list_item_selected_image, null);
//configure the view for this image
String imagePath = getItem(position);
ImageView imageView = (ImageView)convertView.findViewById(R.id.selected_imageImageView);
Bitmap bm = BitmapFactory.decodeFile(imagePath);
//get the screen width at run time
int screenWidth = DeviceDimensionsHelper.getDisplayWidth(getActivity());
//load resized bitmap into an ImageView
imageView.setImageBitmap(BitmapScaler.scaleToFitWidth(bm, screenWidth));
EditText caption = (EditText)convertView.findViewById(R.id.selected_imageCaption);
return convertView;//return view object to the list view
}
}//end private class ImagesAdapter
}//end class PhotosFragment
答案 0 :(得分:1)
解决了这个问题。我使用了onSaveInstanceSate,然后在方法onCreateView中检索了保存的包。
@Override
public void onSaveInstanceState(Bundle savedInstanceState){
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putStringArrayList(KEY_IMAGE_LIST, mSelectedImages);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent
,Bundle savedInstanceState){
View v = inflater.inflate(R.layout.fragment_photos, parent,false);
mSelectedImagesListView = (ListView)v.findViewById(android.R.id.list);
mImagesDescriptionRelativeLayout = (RelativeLayout)
v.findViewById(R.id.photos_descriptionRelativeLayout);
mImagesDescriptionEditText = (EditText)v.findViewById(R.id.photos_descriptionEditText);
mImagesDescriptionRelativeLayout.setVisibility(View.INVISIBLE);
if(savedInstanceState != null){
mSelectedImages = savedInstanceState.getStringArrayList(KEY_IMAGE_LIST);
loadSelectedImagesListView(mSelectedImages);
}
return v;
}//end method onCreateView
答案 1 :(得分:0)
虽然您可以将所选项目存储在onSaveInstanceState
的捆绑包中,但他们必须实施Parcelable
界面。
如果您不想受到保留的约束,请考虑使用无头片段。
public class RetainedFragment extends Fragment {
// data object we want to retain
private MyDataObject data;
// this method is only called once for this fragment
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// retain this fragment
setRetainInstance(true);
}
public void setData(MyDataObject data) {
this.data = data;
}
public MyDataObject getData() {
return data;
}
}
你可以找到更多here,它解释了为什么使用无头片段比仅设置&#34; configChanges&#34;属性。
PS。作为一般经验法则,只对不显示视图的片段使用setRetainInstance(true)
!