I'm using a custom snapping ScrollView in my app. It extends HorizontalScrollView and overrides onTouchEvent(). This is used to snap the child Views in the middle of the ScrollView. There is also a leading and a trailing space which are wide enough so the first and last elements can be placed in the middle.
I use two class variables:
int mActiveFeature //Position of the element nearest to the middle, initially set to 1
List<Integer> mAvailableItems //IDs of contained menu elements in order without the spaces
Here is my onTouchEvent:
@Override
public boolean onTouchEvent(MotionEvent event) {
final int menuItemCount = this.mAvailableItems.size();
switch(event.getAction()) {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
float scrollX = getScrollX();
float layoutWidth =
SnappingScroll.this.getWidth();
float featureWidth =
(int) getResources().getDimension(R.dimen.item_width);
float spaceWidth =
(int) getResources().getDimension(R.dimen.space_width);
View oldItem =
findViewById(
SnappingScroll.this.mAvailableItems.get(
SnappingScroll.this.mActiveFeature - 1
)
);
oldItem.setAlpha(0.5f);
oldItem.setClickable(false);
SnappingScroll.this.mActiveFeature = (int) Math.min(
Math.round((scrollX - spaceWidth + (layoutWidth / 2) + (featureWidth / 2)) / featureWidth),
(float) menuItemCount
);
View newItem =
findViewById(
SnappingScroll.this.mAvailableItems.get(
SnappingScroll.this.mActiveFeature - 1
)
);
newItem.setAlpha(1.0f);
newItem.setClickable(true);
int scrollTo = (int) (
SnappingScroll.this.mActiveFeature * featureWidth
+ spaceWidth
- layoutWidth / 2
- featureWidth / 2
);
smoothScrollTo(scrollTo, 0);
return true;
default:
return super.onTouchEvent(event);
}
}
Here is the XML file I'm using
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
android:orientation="vertical">
<com.example.SnappingScroll
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical">
<Space
android:id="@+id/leading_space"
android:layout_width="@dimen/space_width"
android:layout_height="match_parent" />
<ImageView
android:id="@+id/item_1"
android:layout_width="@dimen/item_width"
android:layout_height="match_parent"
android:alpha="0.5"
android:clickable="false"
android:onClick="clickFunction"
android:src="@drawable/m_1"/>
<ImageView
android:id="@+id/item_2"
android:layout_width="@dimen/item_width"
android:layout_height="match_parent"
android:alpha="0.5"
android:clickable="false"
android:onClick="clickFunction"
android:src="@drawable/m_2"/>
<ImageView
android:id="@+id/item_3"
android:layout_width="@dimen/item_width"
android:layout_height="match_parent"
android:alpha="0.5"
android:clickable="false"
android:onClick="clickFunction"
android:src="@drawable/m_3"/>
<Space
android:id="@+id/trailing_space"
android:layout_width="@dimen/space_width"
android:layout_height="match_parent" />
</LinearLayout>
</com.example.SnappingScroll>
</LinearLayout>
I want all elements at half transparency and not clickable, except the active feature. At the moment, you can scroll, and as you let loose, the View snaps to the nearest element. Then the last snapped to element is deactivated and the new snapped to element is activated. This works fine, but I want the user to see, which element the ScrollView will snap to, as he lifts his finger. So the calculations for the new active feature and the changing of the transparency should be done while scrolling. Is this possible? I already tried to put the code in a case for MotionEvent.ACTION_MOVE, but then the View wasn't scrolling at all. As I put the code into a case for MotionEvent.ACTION_SCROLL, nothing happened and the snapping wasn't triggered.
Edit:
At first, I put the code in an additional OnTouchListener, which was redundant, so now I override the onTouchEvent function and edited the question correspondingly.