I have a simple layout with HorizontalScrollView and horizontal-LinearLayout, like this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="100dp"
android:scrollbars="horizontal"
android:fadingEdge="none">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras sed velit sed nisl pharetra consequat"/>
<TextView
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras sed velit sed nisl pharetra consequat"/>
<TextView ... (same text view repeated several times) />
</LinearLayout>
</HorizontalScrollView>
</RelativeLayout>
When I test this on the emulator, horizontal-fling works great. But testing it on a Samsung Galaxy S2, fling behaves in a strange way:
When the finger moves to-side-and-up, the scroll view starts flinging ok, but before stopping, it bounces and moves back, although it has NOT reached the end. It is as the scrollview is bouncing at any scroll level.
If I just scroll (move the finger to-side-stop-and-up), scroll is done OK.
Has anyone experienced this? Is it any bug in Samsung implementation?
Any ideas on how to fix this?
My app is targeting android 2.2. Galaxy S2 has official Samsung android 4.0.3.
Thanks in advance!
After lots of tests I have come to the conclusion that it is a bug on Samsung firmware (Galaxy S2 4.0.3), on HorizontalScrollView.
It seems that the fling-gesture is being made to the opposite direction that it should: For example, if I press and move to the left, and release the screen, the fling-effect (continue moving and speed down) is done to the... RIGHT!
So my solution has been subclassing HorizontalScrollView, and add a patch to make sure that if the scroll is done to the right, fling is to the right, and viceversa.
public class PatchedHorizontalScrollView extends HorizontalScrollView {
public PatchedHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public PatchedHorizontalScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PatchedHorizontalScrollView(Context context) {
super(context);
}
// store most recent scroll X positions
int olderScrollX = 0;
int lastScrollX = 0;
@Override
public boolean onTouchEvent(MotionEvent ev) {
// keep track of most recent scroll positions
olderScrollX = lastScrollX;
lastScrollX = getScrollX();
return super.onTouchEvent(ev);
}
@Override
public void fling(int velocityX) {
// ensure velocityX has the right sign
if (lastScrollX > olderScrollX) {
// to the right: velocity must be positive
if (velocityX < 0) {
velocityX = -velocityX;
}
} else if (lastScrollX < olderScrollX) {
// to the left: velocity must be negative
if (velocityX > 0) {
velocityX = -velocityX;
}
}
super.fling(velocityX);
}
}