Obsolete
Status Update
Comments
li...@gmail.com <li...@gmail.com> #2
Argh....with this bug there is absolutely no way to determine if the user has changed changed the panning of the map....I need a way to determine this so that i can allow the user to reset the map to it's original view. Please fix this ASAP.
cm...@gmail.com <cm...@gmail.com> #3
I have another example regarding the problematic accuracy of moveCamera/animateCamera.
When you use CameraUpdateFactory.newLatLngBounds(), moveCamera and animateCamera result in different values in map.getProjection().getVisibleRegion().latLngBounds.
LatLngBounds bounds = new LatLngBounds(new LatLng(40.70798493778415, -74.01434069136418), new LatLng(40.72072004852845, -73.99760391411343));
if (animate) {
map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0),
} else {
map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0));
}
map.getProjection().getVisibleRegion().latLngBounds :
after animateCamera -
LatLngBounds{southwest=lat/lng: (40.70711197865251,-74.01539381593466), northeast=lat/lng: (40.72159253556309,-73.99655096232891)}
after moveCamera -
LatLngBounds{southwest=lat/lng: (40.70798500292429,-74.01539381593466), northeast=lat/lng: (40.72071968970514,-73.99655096232891)}
This is pretty important for my design as im calculating a search radius (Vincenty’s formula) by the bounds of the map. appreciate if you could confirm the accuracy of those 2 APIs.
When you use CameraUpdateFactory.newLatLngBounds(), moveCamera and animateCamera result in different values in map.getProjection().getVisibleRegion().latLngBounds.
LatLngBounds bounds = new LatLngBounds(new LatLng(40.70798493778415, -74.01434069136418), new LatLng(40.72072004852845, -73.99760391411343));
if (animate) {
map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0),
} else {
map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0));
}
map.getProjection().getVisibleRegion().latLngBounds :
after animateCamera -
LatLngBounds{southwest=lat/lng: (40.70711197865251,-74.01539381593466), northeast=lat/lng: (40.72159253556309,-73.99655096232891)}
after moveCamera -
LatLngBounds{southwest=lat/lng: (40.70798500292429,-74.01539381593466), northeast=lat/lng: (40.72071968970514,-73.99655096232891)}
This is pretty important for my design as im calculating a search radius (Vincenty’s formula) by the bounds of the map. appreciate if you could confirm the accuracy of those 2 APIs.
gh...@gmail.com <gh...@gmail.com> #5
any news regarding this issue ?
gh...@gmail.com <gh...@gmail.com> #6
I can share my thoughts about it.
LatLng is keeping doubles, when these are sent via IPC, they are flattened to floats, because there is no writeDouble:http://developer.android.com/reference/android/os/Parcel.html#writeFloat%28float%29 .
When going back, you lose precision and thus errors on 4-5th decimal place.
If I'm correct here, this can be hard (if possible) to fix without breaking compatibility.
LatLng is keeping doubles, when these are sent via IPC, they are flattened to floats, because there is no writeDouble:
When going back, you lose precision and thus errors on 4-5th decimal place.
If I'm correct here, this can be hard (if possible) to fix without breaking compatibility.
[Deleted User] <[Deleted User]> #7
If you're right then compatibility doesnt have to be broken in order to pass a more accurate LatLng value in many other parcelable types which are not float. This option can be added and not replace the current one.
I any case this issue is really annoying and i hope someone from google can take a look at it. Thanks.
I any case this issue is really annoying and i hope someone from google can take a look at it. Thanks.
st...@googlemail.com <st...@googlemail.com> #8
If I'm right then you are also right. ;)
Double values in LatLng could be sent using writeLong after converting them using Double.doubleToLongBits (http://docs.oracle.com/javase/7/docs/api/java/lang/Double.html#doubleToLongBits%28double%29 ) and converted back to double in Google Play Services app.
Double values in LatLng could be sent using writeLong after converting them using Double.doubleToLongBits (
dr...@gmail.com <dr...@gmail.com> #9
[Comment deleted]
gd...@gmail.com <gd...@gmail.com> #10
[Comment deleted]
rp...@gmail.com <rp...@gmail.com> #11
Comparing floating-point values for exact equality is rarely a good idea. I'd suggest treating two LatLngs as equal if they're within some small distance of each other.
Not sure what comment #5 is getting at. Parcel#writeDouble exists, and the docs say it's been around since API 1. (Although the docs have been known to lie...)
Not sure what
re...@gmail.com <re...@gmail.com> #12
As you are comparing objects, not numerals, unless specifically otherwise documented, you should expect the equals() method of any class derived from Object to implement the same equivalence relation as the parent class [1]:
"The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true)."
Also, regarding numerals, as the previous commenter already mentioned, comparing floating point values for exact equality is generally not a good idea, and doing it right is far from trivial [2].
Issue 4786 had a similar report about the onCameraChange() event not returning the exact same coordinates originally passed to CameraUpdateFactory.newLatLng().
As I commented there, we need to convert between real-world coordinates and pixel coordinates to render anything on the screen, so especially when it comes to cameras and views, you should not assume the coordinates you gave to exactly match those used internally.
The developer on the other issue provided two (longitude) coordinates as an example: 51.9820167 (given by developer) and 51.982016909253694 (returned by the API). However, the maximum real-world distance between these points is actually only 2.3 cm (at the equator).
If you need to check coordinates for approximate equality, I'd recommend using an arbitrary epsilon value of your choice (e.g. 5 or 10 cm, or 0.000001 degrees) to determine if two points are close enough to each other to be considered equal. You just need to choose a suitable distance metric and epsilon that works well for for your use case.
As we know the number ranges ([-90.0, 90.0] and [-180.0, 180.0) degrees), as well as the approximate minimum resolution of the map, absolute error margins are likely sufficient for most use cases (either in degrees or distance). That way you can avoid having to bother with the less intuitive relative errors mentioned in the linked article.
That said, I changed this issue to a type Enhancement request, and created an internal feature request for providing an a convenience method for calculating approximate equality.
[1]https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-
[2]http://floating-point-gui.de/errors/comparison/
"The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true)."
Also, regarding numerals, as the previous commenter already mentioned, comparing floating point values for exact equality is generally not a good idea, and doing it right is far from trivial [2].
As I commented there, we need to convert between real-world coordinates and pixel coordinates to render anything on the screen, so especially when it comes to cameras and views, you should not assume the coordinates you gave to exactly match those used internally.
The developer on the other issue provided two (longitude) coordinates as an example: 51.9820167 (given by developer) and 51.982016909253694 (returned by the API). However, the maximum real-world distance between these points is actually only 2.3 cm (at the equator).
If you need to check coordinates for approximate equality, I'd recommend using an arbitrary epsilon value of your choice (e.g. 5 or 10 cm, or 0.000001 degrees) to determine if two points are close enough to each other to be considered equal. You just need to choose a suitable distance metric and epsilon that works well for for your use case.
As we know the number ranges ([-90.0, 90.0] and [-180.0, 180.0) degrees), as well as the approximate minimum resolution of the map, absolute error margins are likely sufficient for most use cases (either in degrees or distance). That way you can avoid having to bother with the less intuitive relative errors mentioned in the linked article.
That said, I changed this issue to a type Enhancement request, and created an internal feature request for providing an a convenience method for calculating approximate equality.
[1]
[2]
[Deleted User] <[Deleted User]> #13
[Comment deleted]
me...@gmail.com <me...@gmail.com> #14
an...@gmail.com <an...@gmail.com> #15
Unrelated to this issue, but since my unrelated issue was incorrectly closed as a duplicate...
The current implementation of equals() is just plain wrong. This is a case where comparing floating point values using the == operator is exactly what you want. The current implementation compares the values for bitwise equality, which is wrong in at least two ways: it incorrectly returns true when comparing two NaNs, and it incorrectly returns false when comparing 0f and -0f.
The current implementation of equals() is just plain wrong. This is a case where comparing floating point values using the == operator is exactly what you want. The current implementation compares the values for bitwise equality, which is wrong in at least two ways: it incorrectly returns true when comparing two NaNs, and it incorrectly returns false when comparing 0f and -0f.
su...@gmail.com <su...@gmail.com> #16
Can any one share how to call notifyDataSetChanged? I am using FragmentStatePagerAdapter, ViewPager and Fragments. Not sure where to call it.
st...@gmail.com <st...@gmail.com> #17
Here is a bit of code to get you going
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
public class TabsAdapter extends FragmentStatePagerAdapter implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener {
/**
* just a tab to the fragment adaptor
*
* @param tabSpec
* @param clss
* @param args
*/
public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
tabSpec.setContent(new TabContentFactory(mContext));
String tag = tabSpec.getTag();
TabInfo info = new TabInfo(tag, clss, args);
mTabs.add(info);
mTabHost.addTab(tabSpec);
notifyDataSetChanged();
}
}
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
public class TabsAdapter extends FragmentStatePagerAdapter implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener {
/**
* just a tab to the fragment adaptor
*
* @param tabSpec
* @param clss
* @param args
*/
public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
tabSpec.setContent(new TabContentFactory(mContext));
String tag = tabSpec.getTag();
TabInfo info = new TabInfo(tag, clss, args);
mTabs.add(info);
mTabHost.addTab(tabSpec);
notifyDataSetChanged();
}
}
ap...@gmail.com <ap...@gmail.com> #18
So am i....
al...@gmail.com <al...@gmail.com> #19
NOT works for me with POSITION_NONE, but it works after I copy source code of FragmentStatePagerAdapter and modify destroyItem()
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
Fragment fragment = (Fragment)object;
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
if (DEBUG) Log.v(TAG, "Removing item #" + position + ": f=" + object
+ " v=" + ((Fragment)object).getView());
// while (mSavedState.size() <= position) {
// mSavedState.add(null);
// }
// mSavedState.set(position, mFragmentManager.saveFragmentInstanceState(fragment));
// mFragments.set(position, null);
mFragments.remove(position);
mCurTransaction.remove(fragment);
}
source of FragmentStatePagerAdapterhttp://grepcode.com/file/repo1.maven.org/maven2/com.google.android/support-v4/r7/android/support/v4/app/FragmentStatePagerAdapter.java#FragmentStatePagerAdapter
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
Fragment fragment = (Fragment)object;
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
if (DEBUG) Log.v(TAG, "Removing item #" + position + ": f=" + object
+ " v=" + ((Fragment)object).getView());
// while (mSavedState.size() <= position) {
// mSavedState.add(null);
// }
// mSavedState.set(position, mFragmentManager.saveFragmentInstanceState(fragment));
// mFragments.set(position, null);
mFragments.remove(position);
mCurTransaction.remove(fragment);
}
source of FragmentStatePagerAdapter
fe...@gmail.com <fe...@gmail.com> #20
May 2014
en...@google.com <en...@google.com>
na...@gmail.com <na...@gmail.com> #21
This is a code to reproduce this problem.
https://gist.github.com/takaaki7/645d8d07bbe190eab7bdc55b7f82bb13
I think the cause is in these lines
https://github.com/android/platform_frameworks_support/blob/master/v4/java/android/support/v4/app/FragmentStatePagerAdapter.java#L136-L137
and L94-99
Because following process don't shorten these lists, these and the list ViewPager managing become inconsistent.
mSavedState.set(position, mFragmentManager.saveFragmentInstanceState(fragment));
mFragments.set(position, null);
So following process in instantiateItem() doesn't work correctly and produce these bugs.
if (mFragments.size() > position) {
Fragment f = mFragments.get(position);
if (f != null) {
return f;
}
}
Surely returning POSITION_NONE always in getItemPosition() resolved this problem, but it is inefficient because it instantiate all items that have already been instantiated every time data changed.
And there is a library that resolve these problems by implementing getItemPosition() correctly.
This is it.https://github.com/takaaki7/ArrayPagerAdapter
I think the cause is in these lines
and L94-99
Because following process don't shorten these lists, these and the list ViewPager managing become inconsistent.
mSavedState.set(position, mFragmentManager.saveFragmentInstanceState(fragment));
mFragments.set(position, null);
So following process in instantiateItem() doesn't work correctly and produce these bugs.
if (mFragments.size() > position) {
Fragment f = mFragments.get(position);
if (f != null) {
return f;
}
}
Surely returning POSITION_NONE always in getItemPosition() resolved this problem, but it is inefficient because it instantiate all items that have already been instantiated every time data changed.
And there is a library that resolve these problems by implementing getItemPosition() correctly.
This is it.
[Deleted User] <[Deleted User]> #22
Is this a bug, which will have a fix in a support library? Or is this a normal behaviour?
Description
So I use notifyDataSetChanged on the FragmentPagerAdapter and for getItemPosition() of the old Fragment I return PagerAdapter.POSITION_NONE. But a new element is never acquired using getItem().
After looking at the code, it seems the old fragment is detached and attached back in the same transaction. The instantiateItem() call is using the old Fragment when it should use getItem().