保留配置更改的片段

时间:2016-06-13 08:26:11

标签: android

我有一个由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

2 个答案:

答案 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)