[英]ViewPager and updating Fragments
In my app's activity, I have a ViewPager implementation which loads a Map fragment (FragmentA) on launch and then there are 2 other fragments showing content based on the latitude and longitude selected in FragmentA.在我的应用程序的活动中,我有一个 ViewPager 实现,它在启动时加载一个地图片段 (FragmentA),然后还有 2 个其他片段显示基于 FragmentA 中选择的纬度和经度的内容。
I am unable to get the behavior where upon launch, the latitude/longitude from FragmentA, should be provided to the 2 other fragments and continue to provide whenever user clicks on the map in FragmentA.我无法获得这样的行为:在启动时,FragmentA 的纬度/经度应提供给其他 2 个片段,并在用户单击 FragmentA 中的地图时继续提供。
Here are the approaches I tried:以下是我尝试过的方法:
However, neither of these approaches have worked for me.但是,这两种方法都不适合我。
MyActivity.java //update to show Daniel's suggestion 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 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 /**left out most of map specific code, but I am interested in getting latitude/longitude whenever onConnected()
or onMapClick()
gets called*/ 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 /**in this fragment, I want to refresh content based on latitude/longitude from FragmentA
*/ 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;
}
}
It looks like all you need to complete the implementation is to call handleDataFetch()
from the setNewLatLong()
method if it is a new location.看起来完成实现所需的全部内容就是从setNewLatLong()
方法调用handleDataFetch()
如果它是一个新位置。
This is needed since onCreateView()
won't be called due to the Fragment being in a ViewPager, so the best way to get the updated location info to FragmentB when it is displayed is to just use a public method called from the ViewPager.OnPageChangeListener
in the Activity, as you are doing here.这是必需的,因为由于 Fragment 位于 ViewPager 中,因此不会调用onCreateView()
,因此在显示 FragmentB 时将更新的位置信息获取到 FragmentB 的最佳方法是使用从ViewPager.OnPageChangeListener
调用的公共方法在 Activity 中,正如您在这里所做的那样。
Just be sure that your equals()
method override is implemented correctly in the UserLatLong
class, and add this to the setNewLatLong()
method:只需确保在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.