I\'m writing my own image viewer that enables users to swipe left\\right to see the next\\previous image. I want to animate the image change according to the fling velocity.
How come different devices with same density and almost same api level don't have the same max velocity?
Min and max velocity parameters are set by the manufacturer. Different device models will often use the same density bucket for resource selection purposes, but don't normally share the same physical density. Assume the existence of a 4" phone and a 5" phone with identical resolutions and an identical reported density of 1.5. Imagine swiping over both screens at the same physical speed. The reported pixels/second would be higher on the small screen despite the fact that both phones have identical resolutions and reported densities.
What to do with min and max velocity? Lets say the maker of the smaller screen determines 75 pixels/second is the perfect minimum finger velocity before reporting a fling gesture. Any smaller would result in accidental flings from touch error, any larger would require too deliberate of a gesture to fling something. If the manufacturer of the large phone wanted to match the same perfect physical behavior (same finger speed) of the smaller phone, they would need to adjust the minimum velocity to be a smaller number. The maker of the larger device would require less pixels/second to initiate a fling due to physical characteristics. Other factors like screen sensitivity probably factor in for different manufacturers.
How can I get the same experience on different devices when a user makes a swipe gesture?
Use the velocity given in pixels/second to configure the animations. Simply avoid the use of density independent parameters and you should be able to match the velocity exactly. Notice that this has nothing to do with the min or max velocity values. However, you would want to calculate your SWIPE_THRESHOLD_VELOCITY to be a 'raw' pixel value based on the stated density. This is how Android's Launcher2 calculates density independent threshold velocity for home screen item flings:
int DENSITY_INDEPENDENT_THRESHOLD = 200;
Resources r = getResources();
float density = r.getDisplayMetrics().density;
SWIPE_THRESHOLD_VELOCITY = (int)(DENSITY_INDEPENDENT_THRESHOLD * density);
Notice this threshold would be the same for both the 4" phone and the 5" phone in the example above. This does not affect actual velocities because we're only talking about a threshold here. You would simply need to swipe 20% faster on the 5" phone than on the 4" phone to break the threshold. The Android launcher uses a DENSITY_INDEPENDENT_THRESHOLD of -1500 in the y direction, but 200 sounds about right for your application.
Can I use the max velocity data to make a uniform experience across all Android devices?
No. Max velocity is an edge case you don't need to animate correctly. I doubt users will fling anything at the max velocity unless they're playing a game, and users won't care if the animation matches perfectly at a velocity of 6000 pixels/second anyway.
TL;DR Use raw velocities from onFling arguments to configure animations and match speeds exactly. Avoid using density independent parameters to configure fling animations.