簡體   English   中英

ViewPager 和更新片段

[英]ViewPager and updating Fragments

在我的應用程序的活動中,我有一個 ViewPager 實現,它在啟動時加載一個地圖片段 (FragmentA),然后還有 2 個其他片段顯示基於 FragmentA 中選擇的緯度和經度的內容。

我無法獲得這樣的行為:在啟動時,FragmentA 的緯度/經度應提供給其他 2 個片段,並在用戶單擊 FragmentA 中的地圖時繼續提供。

以下是我嘗試過的方法:

  1. 使用接口在片段 -> 活動 -> 片段之間進行通信(堅持這種方法
  2. 當片段被初始化時,使用 bundle 在片段之間傳遞信息

但是,這兩種方法都不適合我。

MyActivity.java //更新以顯示丹尼爾的建議

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;
   }

}

看起來完成實現所需的全部內容就是從setNewLatLong()方法調用handleDataFetch()如果它是一個新位置。

這是必需的,因為由於 Fragment 位於 ViewPager 中,因此不會調用onCreateView() ,因此在顯示 FragmentB 時將更新的位置信息獲取到 FragmentB 的最佳方法是使用從ViewPager.OnPageChangeListener調用的公共方法在 Activity 中,正如您在這里所做的那樣。

只需確保在UserLatLong類中正確實現了您的equals()方法覆蓋,並將其添加到setNewLatLong()方法中:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM