Android:在viewpager片段内重用支持映射片段以保持FULL状态

时间:2015-06-04 02:40:23

标签: android google-maps android-fragments android-viewpager google-maps-android-api-2

我有一个使用actionbarsherlock和谷歌地图的应用程序。我在应用程序中有3个主要选项卡,当您导航两个选项卡时,第一个选项卡将被销毁。我将setOffscreenPageLimit()设置为2,但我想正确解决此问题,有时当用户返回到地图视图时,地图为空且无响应。我将片段保存在我的操作栏活动中的一个数组中,以防止它们被破坏,这曾经与之前版本的google play一起使用,但是在迁移到7.0.0时我不得不重构我的代码。我对片段缺乏经验,所以问题可能就在那里,尽管地图的缩放和位置都是保持不变的(选项,标记等等)。

我的代码如下:

修改

当我回来时,地图会保存我的缩放和我正在寻找的位置,但是听众和标记都消失了。任何使用地图的任务都不再连接

// ActionBarActivity.java

public class ActionBarActivity extends SherlockFragmentActivity implements TabListener, OnPageChangeListener {
    ViewPager mViewPager;
    String pageString = "map_view";
    // Holder for the fragments used
    List<SherlockFragment> frags;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_action_bar);

        mViewPager = (ViewPager) findViewById(R.id.pager);

        // *** I would like for the code to work WITHOUT the following line ***
        mViewPager.setOffscreenPageLimit(2);

        mViewPager.setAdapter(new MyPagerAdapter(this, getSupportFragmentManager()));

        // Get Actionbar
        ActionBar bar = getSupportActionBar();

        // Get tabs
        ActionBar.Tab mapTab = bar.newTab()
                .setIcon(R.drawable.ic_action_map)
                .setTabListener(this)
                .setTag("map");

        ActionBar.Tab listTab = bar.newTab()
                .setIcon(R.drawable.ic_action_view_as_list)
                .setTabListener(this)
                .setTag("list");

        // Get tabs
        ActionBar.Tab photoFeedTab = bar.newTab()
                .setIcon(R.drawable.ic_action_camera)
                .setTabListener(this)
                .setTag("photo");


        bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        bar.addTab(mapTab);
        bar.addTab(listTab);
        bar.addTab(photoFeedTab);

        frags = Arrays.asList(null, null, null);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mViewPager.setOnPageChangeListener(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        mViewPager.setOnPageChangeListener(null);
    }

    private class MyPagerAdapter extends FragmentStatePagerAdapter {
        private final String[] mPageTitles;

        public MyPagerAdapter(Context context, FragmentManager fm) {
            super(fm);
            mPageTitles = context.getResources().getStringArray(R.array.pageTitle);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return mPageTitles[position];
        }

        @Override
        public int getCount() {
            return mPageTitles.length;
        }

        @Override
        public Fragment getItem(int position) {
            Fragment f = null;
            switch (position) {
                case 0:
                    pageString = "map_view";
                    if(frags.get(0) == null) {
                        ViewMap vm = new ViewMap();
                        vm.setRetainInstance(true);
                        frags.set(0, vm);
                    }
                    f = frags.get(0);
                    // pass through the bundle holding lat/long
                    // to move the camera (if present)
                    Bundle showData = getIntent().getExtras();
                    if (showData != null) {
                        f.setArguments(showData);
                    }
                    break;
                case 1:
                    pageString = "list_view";
                    if(frags.get(1) == null) {
                        frags.set(1, new ListViewHubba());
                    }
                    f = frags.get(1);
                    break;
                case 2:
                    pageString = "Photo_feed";
                    if(frags.get(2) == null) {
                        frags.set(2, new PhotoFeedList());
                    }
                    f = frags.get(2);
                    break;
            }
            return f;
        }
    }

    public void onPageScrollStateChanged(int arg0) {
    }

    public void onPageScrolled(int arg0, float arg1, int arg2) {
    }

    public void onPageSelected(int position) {
        position = position % getSupportActionBar().getNavigationItemCount();
        getSupportActionBar().setSelectedNavigationItem(position);
    }

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        mViewPager.setCurrentItem(tab.getPosition());
    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {
    }
}

// ViewMap.java

public class ViewMap extends SherlockFragment {

    public GoogleMap mMap;
    private View rootView = null;
    Context context;
    private View v;
    ProgressDialog progressDialog;
    boolean fetched = false;
    SupportMapFragment fragment;

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        FragmentManager fm = getChildFragmentManager();
        fragment = getMapFragment();
        if (fragment == null) {
            Log.i("DEBUG", "Fragment was null.");
            fragment = SupportMapFragment.newInstance();
            fragment.setRetainInstance(true);
            fm.beginTransaction().replace(R.id.map_container, fragment).commit();
        } else {
            Log.i("DEBUG", "Fragment was Not null.");
        }


    /**
     * at this time google play services are not initialize so get map
     * and add what ever you want to it in onResume() or onStart()
     */
    }

    @Override
    public void onResume() {
        super.onResume();

        setupMapIfNeeded();
    }

    public View onCreateView(final LayoutInflater inflater,
                             final ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        context = getActivity().getApplicationContext();
        if(rootView == null) {
            rootView = inflater.inflate(R.layout.view_map_activity, container,
                    false);
        } else {
            Log.i("DEBUG", "Non null root view.");
        }
        return rootView;
    }

    public void setupMapIfNeeded() {
        if (mMap == null) {
            mMap = fragment.getMap();
            fetched = false;
        }

        // Check if we were successful in obtaining the map.
        // and only reload it if we haven't already fetched
        if (mMap != null && !fetched) {
            mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
            isHybrid = false;
            mMap.setMyLocationEnabled(true);

                // Check if current location is available, otherwise default to riley
                LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
                Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                LatLng Center;
                if (location != null) {
                    // Get current location info
                    Center = new LatLng(location.getLatitude(), location.getLongitude());
                } else {
                    // default to riley
                    Center = new LatLng(42.4409010, -83.3978000);
                }

                // set camera position
                CameraPosition cameraPosition = new CameraPosition.Builder()
                        .target(Center)
                        .zoom(CAMERA_ZOOM)
                        .bearing(0)
                        .tilt(30)
                        .build();
                mMap.animateCamera(CameraUpdateFactory
                        .newCameraPosition(cameraPosition));

            /**
             * Show loading message if first time fetching.
             */
            progressDialog = ProgressDialog.show(getActivity(), "",
                    "Fetching spots...", true);

            Spot.getAllSpots(mMap, getActivity().getApplicationContext(), progressDialog);
            fetched = true;

            //... custom map options here ...
        }
    }

    private SupportMapFragment getMapFragment() {
        FragmentManager fm = null;

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            Log.i("DEBUG", "using getFragmentManager");
            fm = getFragmentManager();
        } else {
            Log.i("DEBUG", "using getChildFragmentManager");
            fm = getChildFragmentManager();
        }

        return (SupportMapFragment) fm.findFragmentById(R.id.map_container);
    }
}

// view_map_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/map_view_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/map_container">

        <!-- The map fragment will go here -->

    </RelativeLayout>
</RelativeLayout>

我没有收到任何错误/崩溃但是当我从最右边的选项卡返回到地图视图时,我的缩放和位置仍然存在,但所有标记都消失了。当片段被导航回来时,我有一个解决方法可以将它们添加回来 - 但由于我有很多标记,所以它太慢了。

有没有人知道如何保持嵌套的子supportmapfragment?我已经在这方面工作了很长时间,并且可以真正使用一些帮助......

1 个答案:

答案 0 :(得分:1)

你可以使用:

setRetainInstance(true);

在onCreate()方法中,要求supportmapfragment在回收地图时保留点等。无论如何,这可能需要时间来保存和恢复数千个标记,而你没有其他选择,大数据是大数据:D

编辑:无论如何,你似乎已经保留了实例......这有用吗?

<强> EDIT2: 查看地图演示,有一个“MapRetain”在我的设备上运行。也许您对片段的所有触摸和“SupportMapFragment.newInstance()”会破坏所有内容......

/**
 * This shows how to retain a map across activity restarts (e.g., from screen rotations), which can
 * be faster than relying on state serialization.
 */
public class RetainMapDemoActivity extends FragmentActivity implements OnMapReadyCallback {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.basic_demo);

        SupportMapFragment mapFragment =
                (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);

        if (savedInstanceState == null) {
            // First incarnation of this activity.
            mapFragment.setRetainInstance(true);
        }

        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap map) {
        map.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
    }
}