Reputation: 1817
I have a scrollView with lot of elements
ScrollView scroller = (ScrollView)findViewById(R.id.scrollView);
I need to attach an onClickListener to the scrollview so I do
scroller.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// This is all you need to do to 3D flip
AnimationFactory.flipTransition(viewAnimator, FlipDirection.LEFT_RIGHT);
}
});
But this is not getting triggered when I touch. Any Ideas?
Upvotes: 23
Views: 24286
Reputation: 2681
It is because the child of the ScrollView
is getting the touch event of the user and not the ScrollView
. You must set android:clickable="false"
attribute to each and every child of the ScrollView
for the onClickListener
to work on ScrollView
.
Or else the alternate could be to set the onClickListener
on each of the ScrollView's children and handle it.
Upvotes: 11
Reputation: 334
As @Zain pointed out, sometimes it is necessary to capture OnClicks for the whole area of the Scrollview, while the childs may be smaller or invisible. To circumvent scrolling detected as an onClick, we used a GestureDetector:
final protected GestureDetector gestureDetector = new GestureDetector(getActivity(),
new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
});
in onCreateView
scrollView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(gestureDetector.onTouchEvent(event)){
[do stuff]
}
return false;
}
});
Upvotes: 2
Reputation: 40830
sadly this also triggers after each scroll event.
This the actually the answer to the question without any odd cases by using View.OnTouchListener
instead of View.OnClickListener
on the ScrollView
and detecting the MotionEvent.ACTION_UP
where the finger is left off the screen.
To make sure that it's not a scroll, then save previous touched screen x, y values of the MotionEvent.ACTION_DOWN
and compare it to those of MotionEvent.ACTION_UP
. If they are not equal then certainly the user is moving their finger (i.e. scrolling) before they left it off the screen.
int mXOld, mYOld; // field values to save the tap down on the ScrollView
scrollView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mXOld = x;
mYOld = y;
} else if (event.getAction() == MotionEvent.ACTION_UP) {
if (x == mXOld || y == mYOld) { // detecting it's not a horizontal/vertical scrolling in ScrollView
// HERE add the code you need when the ScrollView is clicked
Toast.makeText(MainActivity.this, "Click", Toast.LENGTH_SHORT).show();
return false;
}
}
return false;
}
});
My problem was somehow different, so I wanted to share it..
I have a ScrollView
that I have to use match_parent
in its width & height; and I have an internal TextView
that is centered in the ScrollView
.
The text of the TextView
can be long so it occupies the full height of the ScrollView
, and sometimes it can be short, so there will be blank areas on the top and bottom., So setting the OnClickListener
on the TextView
didn't help me whenever the text is short as I want the blank areas detects the click event as well; and also the OnClickListener
on the ScrollView
doesn't work..
So, I solved this by setting OnTouchListener
on the ScrollView
and put code into MotionEvent.ACTION_UP
So it can kind of simulating complete tap by lefting off the finger off the screen.
private View.OnTouchListener mScrollViewTouchListener = new View.OnTouchListener() {
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
// DO Something HERE...
}
return false;
}
};
Upvotes: 3
Reputation: 165
I think you can custom a ScrollView, override the dispatchTouchEvent method, add add the custom onClick callback.
Upvotes: 0
Reputation: 630
The best solution seem to put LinearLayout
into ScrollView
and set the setOnClickListener
on it.
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/myLayout"
android:clickable="true"
android:orientation="vertical">
<!-- content here -->
</LinearLayout>
</ScrollView>
in the Activity :
LinearLayout lin = (LinearLayout) fragment.rootView.findViewById(R.id.myLayout);
lin.setOnTouchListener(new setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Whatever
}
});
Upvotes: 14
Reputation: 13548
You need to set the setOnClickListener
directly on the ScrollView's child.
Since a ScrollView can have only one child, you can simply use this approach:
ScrollView scrollView = //...
View.OnClickListener mOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
// ...
}
//Set the onClickListener directly on the ScrollView's child
scrollView.getChildAt(0).setOnClickListener(mOnClickListener);
Upvotes: 13