ViewPager和更新碎片

时间:2016-10-08 13:38:38

标签: android android-fragments android-viewpager android-maps-v2

在我的应用程序活动中,我有一个ViewPager实现,它在启动时加载一个Map片段(FragmentA),然后还有另外两个片段显示基于FragmentA中选择的纬度和经度的内容。

我无法获得启动时的行为,FragmentA的纬度/经度应该提供给其他2个片段,并在用户点击FragmentA中的地图时继续提供。

以下是我尝试的方法:

  1. 使用接口在片段之间进行通信 - >活动 - >片段(坚持这种方法
  2. 在片段初始化时使用bundle在片段之间传递信息
  3. 然而,这些方法都不适用于我。

    MyActivity.java //更新以显示Daniel的建议

    public class MyDemoActivity extends FragmentActivity
                    implements FragmentA.OnFragmentInteractionListener,
                        FragmentB.OnFragmentInteractionListener, IUserLatLong  {
    
        private MyPagerAdapter pagerAdapter;
    
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.map_in_pager_demo);
    
            ViewPager mPager = (ViewPager) findViewById(R.id.pager);
            pagerAdapter = new MyPagerAdapter(getSupportFragmentManager(), getApplicationContext());
            mPager.setAdapter(pagerAdapter);
    
            //always start w/ Maps View, FragmentA
            mPager.setCurrentItem(1);
    
            //
            mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
               @Override
               public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                //do something
               }
    
               @Override
               public void onPageSelected(int position) {
                 // do this instead of calling, notifyDataSetChanged()
                Fragment frag = pagerAdapter.fragments[position];
                if (frag != null && frag instanceof FragmentB) {
                    Log.i(TAG, "::FragmentB:: Fetching data from Activity");
                    //here is my confusion, calling FragmentB with latlong from FragmentA
                    ((FragmentB) frag).setNewLatLong(newUserLatLong);
                }
               }
    
               @Override
               public void onPageScrollStateChanged(int state) {
                 //do something
               }
           });
        }
    
        @Override
        public void onFragmentInteraction(Uri uri) {
            //do something
        }
    
        @Override
        public void makeUseOfNewLocation(UserLatLong userLatLong) {
           newUserLatLong = userLatLong;
           Log.i(TAG, "LatLong from FragmentA is: " + newUserLatLong.getLat()
                    + " and long is: " + newUserLatLong.getLng());
        }
    
    /**
     * Used for fetching data from activity
     * @return
     */
    public UserLatLong getLLFromActivity() {
          if(newUserLatLong == null) {
            Log.e(TAG, "LatLong from FragmentA came up empty");
          } else {
    
            Log.i(TAG, "LatLong from FragmentA IS NOT empty: " + newUserLatLong.getLat()
                    + " and long is: " + newUserLatLong.getLng());
          }
          return newUserLatLong;
        }
    
    }
    

    MyPagerAdapter.java

    public class MyPagerAdapter extends FragmentPagerAdapter {
    
        private static int NUM_ITEMS = 3;
        public MyPagerAdapter(FragmentManager fm, Context context) {
           super(fm);
           this.context = context; 
        }
    
        @Override
        public int getCount() {
            return NUM_ITEMS;
        }
    
        // not sure if this is really helping
        @Override
        public int getItemPosition(Object object) {
            // POSITION_NONE makes it possible to reload the PagerAdapter
            return POSITION_NONE;
        }
    
        @Override
        public Fragment getItem(int position) {
            switch (position) {
                case 0:
                    //uses location from FragmentA to get data
                    return new FragmentB();
                case 1:
                    //loads map and gets location
                    return new FragmentA();
                case 2:
                    //uses location from FragmentA to get data
                    return new FragmentC();
                default:
                    return null;
            }
        }
    
       //This populates your Fragment reference array:
       @Override
       public Object instantiateItem(ViewGroup container, int position) {
           Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
           fragments[position]  = createdFragment;
           Log.i(TAG, "::instantiateItem:: " + position + " " + createdFragment.toString());
           return createdFragment;
        }
    
    }
    

    FragmentA.java / **遗漏了大部分地图特定代码, 但我有兴趣在onConnected()onMapClick()被调用时获得纬度/经度* /

    @Override
    public void onConnected(@Nullable Bundle bundle) {
         Log.i(TAG, "In onConnected(), Google API client is:: " + mGoogleApiClient.isConnected());
    
         if (mGoogleApiClient != null) {
             try {
                    // Get last known recent location.
                    mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
    
                    if (mCurrentLocation != null) {
                        // Print current location if not null
                        final LatLng latLng = new LatLng(mCurrentLocation.getLatitude(),
                                                            mCurrentLocation.getLongitude());
    
                        //wrap LatLng into UserLatLong
                        userLatLong.setLat(latLng.latitude);
                        userLatLong.setLng(latLng.longitude);
    //updating the value in the interface
                        mLLCallback.makeUseOfNewLocation(userLatLong);
    
                        CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 20);
                        mMap.animateCamera(cameraUpdate);
                        mMap.addMarker(new MarkerOptions().position(latLng));
                        Log.i(TAG, "::Google::My current location set::");
    
                        mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
                            @Override
                            public void onMapClick(LatLng latLng1) {
                                mMap.clear(); //removes the previous marker
                                mMap.addMarker(new MarkerOptions().position(latLng1));
    
                    //updating the value in the interface
                    mLLCallback.makeUseOfNewLocation(userLatLong);
                                float x = (float) latLng1.latitude;
                                float y = (float) latLng1.longitude;
                                Log.d(TAG, "Map clicked w/ lat: " + x + " and long: " + y);
    
                                //wrap LatLng into UserLatLong
                                userLatLong.setLat(latLng1.latitude);
                                userLatLong.setLng(latLng1.longitude);
    
                            }
                        });
    
                    mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
    
                        //for zooming automatically to the location of the marker
                        CameraPosition cameraPosition = new CameraPosition.Builder().target(latLng).zoom(12).build();
                        mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
    
                        //TODO: Constrain the camera target to bounds defined by API
                        mMap.setMinZoomPreference(Constants.DEFAULT_MIN_ZOOM);
                        mMap.setMaxZoomPreference(Constants.DEFAULT_MAX_ZOOM);
    
                    } else {
                        Toast.makeText(getActivity(), "Current location is null", Toast.LENGTH_SHORT).show();
                    }
                } catch (SecurityException se1) {
                    Log.e(TAG, "SecurityException1: " + se1.getLocalizedMessage());
                }
    
            } else {
                Toast.makeText(getActivity(), "Google API client is null!", Toast.LENGTH_SHORT).show();
            }
    
    此片段中的

    FragmentB / **,我想根据FragmentA * /

    中的纬度/经度刷新内容
    public class FragmentB extends Fragment {
        /**
         * Required empty public constructor
         */
        public FragmentB() {
        }
    
    
    /**the getArguments() is always null*/
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        currLatLong = getNewLatLong();
        }
    
        /**I want latitude/longitude from FragmentA before onCreateView gets called*/ 
        @Override
        public View onCreateView(LayoutInflater inflater, final ViewGroup container,
                                 Bundle savedInstanceState) {
    
            LayoutInflater inflater1 = LayoutInflater.from(getContext());
            // Inflate the layout for this fragment
            view = inflater1.inflate(R.layout.fragment_a, container, false);
           currLatLong = getNewLatLong();
            //fetch my list based on LatLong
            handleDataFetch(currLatLong);
    
            return view;
        }
    
        //
        private void handleDataFetch(UserLatLong newLatLong) {
            final UserLatLong latLong = newLatLong;
            final APIEndpointI apiEndpointI = APIRequests.getClient().create(APIEndpointI.class);
    
            String userId = "XXXX-XXX-XXXXXXX";
    
            currLatLong = new UserLatLong(newLat.doubleValue(), newLong.doubleValue());
            if (currLatLong != null) {
                Log.i(TAG, "Finally! Lat is: " + currLatLong.getLat() +
                        " and Long is:" + currLatLong.getLng());
                /**using retrofit*/
                Call<MyResp> call = apiEndpointI.getMyList(userId, currLatLong);
                call.enqueue(new Callback<MyResp>() {
                    @Override
                    public void onResponse(Call<MyResp> call, Response<MyResp> response) {
    
    
                        Log.i(TAG, "Count: " + response.body().getBundles().size());
                        Resources res = getContext().getResources();
                        String cntString = String.format(res.getString(R.string.count), response.body().getBundles().size());
                        tv1.setText(cntString);
    
                        //Initialize with empty data
                        mGridData = new ArrayList<>();
                        mGridAdapter = new ProfilePicAdapter(getActivity(), R.layout.grid_item_layout, mGridData);
                        mGridView.setAdapter(mGridAdapter);
    
                       }    
                    @Override
                    public void onFailure(Call<MyResp> call, Throwable t) {
                        //do something here
                        Log.d(TAG, "Failed to get response for GetMyList(): " + t.getMessage());
                    }
                });
            } else {
                Log.e(TAG, "In onCreateView(), lat long are empty");
            }
        }
    
    
       //called from activity to pass the latest latlong
       public void setNewLatLong(UserLatLong userLatLong) {
          currLatLong = userLatLong;
       }
    
       //called from activity to pass the latest latlong
       private UserLatLong getNewLatLong() {
          return currLatLong;
       }
    
    }
    

1 个答案:

答案 0 :(得分:2)

看起来完成the implementation所需要的就是从handleDataFetch()方法调用setNewLatLong()(如果它是新位置)。

由于Fragment位于ViewPager中,因此不会调用onCreateView(),因此在显示时将更新的位置信息提供给FragmentB的最佳方法是使用名为的公共方法来自活动中的ViewPager.OnPageChangeListener,正如您在此处所做的那样。

请确保equals()类正确实施UserLatLong方法覆盖,并将其添加到setNewLatLong()方法:

   //called from activity to pass the latest latlong
   public void setNewLatLong(UserLatLong userLatLong) {
      //Added:
      if (!currLatLong.equals(userLatLong)) {
          handleDataFetch(userLatLong);
      }
      currLatLong = userLatLong;
   }