Reputation: 8145
I would like to enable ScrollView and disable it by a Button Click.
Disable means like if the ScrollView wasn't there, and enable it returns the ScrollView.
I want that because I have a gallery with text images, and on a button click the screen orientation changes, so in Landscape the text becomes bigger. And I want the ScrollView so the image does not stretch itself and the text becomes unreadable.
scrollview.Enabled=false / setVisibility(false)
doesn't make anything.
xml:
<ScrollView
android:id="@+id/QuranGalleryScrollView"
android:layout_height="fill_parent"
android:layout_width="fill_parent">
<Gallery android:id="@+id/Gallery"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="horizontal"></Gallery>
</ScrollView>
I can't use Visibility (gone) since that would also hide the Gallery, what I want is to hide the effect of the ScrollView. When there is ScrollView, the images in Gallery become scrollable and do not fit in the screen so you have to scroll to see the whole image. I don't want to disable/enable that on a button click.
I tried this:
((ScrollView)findViewById(R.id.QuranGalleryScrollView)).setOnTouchListener(null);
((ScrollView)findViewById(R.id.QuranGalleryScrollView)).setHorizontalScrollBarEnabled(false);
((ScrollView)findViewById(R.id.QuranGalleryScrollView)).setVerticalScrollBarEnabled(false);
((ScrollView)findViewById(R.id.QuranGalleryScrollView)).setEnabled(false);
But still the images in the Gallery are scrollable and not fit the screen. What's the solution to this?
Upvotes: 117
Views: 159721
Reputation: 1367
Kotlin:
scrollView.setOnTouchListener { _, _ -> true }
Upvotes: 1
Reputation: 633
Here is a Kotlin extension
@SuppressLint("ClickableViewAccessibility")
fun NestedScrollView.disableScroll() {
this.setOnTouchListener { _, _ ->
true
}
}
@SuppressLint("ClickableViewAccessibility")
fun NestedScrollView.enableScroll() {
this.setOnTouchListener { _, _ ->
false
}
}
@SuppressLint("ClickableViewAccessibility")
fun ScrollView.disableScroll() {
this.setOnTouchListener { _, _ ->
true
}
}
@SuppressLint("ClickableViewAccessibility")
fun ScrollView.enableScroll() {
this.setOnTouchListener { _, _ ->
false
}
}
Upvotes: 0
Reputation: 485
Extend ScrollView
and override onInterceptTouchEvent
to return false
, in Kotlin:
class SV(context: Context) : HorizontalScrollView(context) {
var allowUserScroll = false
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
return if (allowUserScroll) super.onInterceptTouchEvent(ev) else false
}
}
That's enough!
(The advantage over using setOnTouchListener
is that this way the disabled ScrollView
does not interfere with touch event handling of descendants in any way)
Upvotes: 2
Reputation: 23432
Several points to begin with:
onTouchEvent
method to return false
when some condition is matched.android:scaleType
property (XML) or the setScaleType
method - for instance ScaleType.CENTER
will not stretch your image and will center it at it's original size You could modify ScrollView
as follows to disable scrolling
class LockableScrollView extends ScrollView {
...
// true if we can scroll (not locked)
// false if we cannot scroll (locked)
private boolean mScrollable = true;
public void setScrollingEnabled(boolean enabled) {
mScrollable = enabled;
}
public boolean isScrollable() {
return mScrollable;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
// if we can scroll pass the event to the superclass
return mScrollable && super.onTouchEvent(ev);
default:
return super.onTouchEvent(ev);
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// Don't do anything with intercepted touch events if
// we are not scrollable
return mScrollable && super.onInterceptTouchEvent(ev);
}
}
You would then use
<com.mypackagename.LockableScrollView
android:id="@+id/QuranGalleryScrollView"
android:layout_height="fill_parent"
android:layout_width="fill_parent">
<Gallery android:id="@+id/Gallery"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="horizontal">
</Gallery>
</com.mypackagename.LockableScrollView>
in your XML file (just changed the ScrollView
to your special LockableScrollView
).
Then call
((LockableScrollView)findViewById(R.id.QuranGalleryScrollView)).setScrollingEnabled(false);
to disable scrolling of the view.
I think that you have more than just the issue of disabling scrolling though to achieve your desired result (the gallery will remain scrollable with the above code for instance) - I'd recommend doing some more research on each of the three components (Gallery, ScrollView, ImageView) to see what properties each one has and how it behaves.
Upvotes: 201
Reputation: 431
public class LockableScrollView extends ScrollView {
private boolean mScrollable = true;
public LockableScrollView(Context context) {
super(context);
}
public LockableScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public LockableScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public LockableScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public void setScrollable(boolean enabled) {
mScrollable = enabled;
}
public boolean isScrollable() {
return mScrollable;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
return mScrollable && super.onTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mScrollable && super.onInterceptTouchEvent(ev);
}
}
Upvotes: 1
Reputation: 129
You can make a CustomScrollView, for which you can disable its interference with other views. Though this can be sometimes irritating for the end user. Use it with caution.
This is the code:
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewParent;
public class CustomScrollView extends android.widget.ScrollView {
public CustomScrollView(Context context) {
super(context);
}
public CustomScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
/* Prevent parent controls from stealing our events once we've gotten a touch down */
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN)
{
ViewParent p = getParent();
if (p != null)
p.requestDisallowInterceptTouchEvent(true);
}
return false;
}
}
How to use the CustomScrollView?
You can add CustomScrollView as a parent to the screen in which you want to add another Scrollview as a child view, and the whole screen is scrollable. I used this for a RelativeLayout.
<?xml version="1.0" encoding="utf-8"?>
<**package.**CustomScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/some_id"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:tools="http://schemas.android.com/tools">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
#**Inside this I had a TableLayout and TableRow. Inside the TableRow,**
#**I had a TextView which I made scrollable from Java Code.**
#**textView.setMovementMethod(new ScrollingMovementMethod());**
</RelativeLayout>
</ankit.inventory.ankitarora.inventorymanagementsimple.CustomScrollView>
It worked for my case.
Upvotes: 1
Reputation: 5540
I had a layout over the NestedScrollView consuming the touch event and disable the scroll:
progressBarLayout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return true;
}
});
and to enable:
progressBarLayout.setOnTouchListener(null);
Upvotes: 3
Reputation: 1077
I had gone this way:
scrollView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return isBlockedScrollView;
}
});
Upvotes: 80
Reputation: 139
to start, i used the Code posted posted in the first Comment but i changed it like this:
public class LockableScrollView extends ScrollView {
public LockableScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public LockableScrollView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public LockableScrollView(Context context)
{
super(context);
}
// true if we can scroll (not locked)
// false if we cannot scroll (locked)
private boolean mScrollable = true;
public void setScrollingEnabled(boolean enabled) {
mScrollable = enabled;
}
public boolean isScrollable() {
return mScrollable;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
// if we can scroll pass the event to the superclass
if (mScrollable) return super.onTouchEvent(ev);
// only continue to handle the touch event if scrolling enabled
return mScrollable; // mScrollable is always false at this point
default:
return super.onTouchEvent(ev);
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
// if we can scroll pass the event to the superclass
if (mScrollable) return super.onInterceptTouchEvent(ev);
// only continue to handle the touch event if scrolling enabled
return mScrollable; // mScrollable is always false at this point
default:
return super.onInterceptTouchEvent(ev);
}
}
}
then i called it in by this way
((LockableScrollView)findViewById(R.id.scrollV)).setScrollingEnabled(false);
because i tried
((LockableScrollView)findViewById(R.id.scrollV)).setIsScrollable(false);
but it said that setIsScrollable is undefined
i hope this will help you
Upvotes: 5
Reputation: 717
Found this simple solution just set
ScrollView.requestDisallowInterceptTouchEvent(true);
Upvotes: 15
Reputation: 109
Disablend ScrollView
ScrollView sw = (ScrollView) findViewById(R.id.scrollView1);
sw.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
Upvotes: 9
Reputation: 8925
@JosephEarl +1 He has a great solution here that worked perfectly for me with some minor modifications for doing it programmatically.
Here are the minor changes I made:
LockableScrollView Class:
public boolean setScrollingEnabled(boolean enabled) {
mScrollable = enabled;
return mScrollable;
}
MainActivity:
LockableScrollView sv;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sv = new LockableScrollView(this);
sv.setScrollingEnabled(false);
}
Upvotes: 1
Reputation: 418
You can extend the gallery and use some flag to disable scrolling when you want:
public class MyGallery extends Gallery {
public boolean canScroll;
public MyGallery(Context context, AttributeSet attrs) {
canScroll = true;
super(context, attrs);
}
public void setCanScroll(boolean flag)
{
canScroll = flag;
}
@Override
public boolean onScroll(android.view.MotionEvent e1, android.view.MotionEvent e2, float distanceX, float distanceY) {
if (canScroll)
return super.onScroll(e1,e2,distancex,distancey);
else
return false;
}
@Override
public boolean onSingleTapUp(MotionEvent e)
{
if (canScroll)
return super.onSingleTapUp(ey);
else
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
{
if (canScroll)
return super.onFling(e1,e2,velocityX,velocityY);
else
return false;
}
}
Upvotes: 0
Reputation: 1259
I don't have enough points to comment on an answer, but I wanted to say that mikec's answer worked for me except that I had to change it to return !isScrollable like so:
mScroller.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return !isScrollable;
}
});
Upvotes: 5
Reputation: 2795
on button click listener just do
ScrollView sView = (ScrollView)findViewById(R.id.ScrollView01);
sView.setVerticalScrollBarEnabled(false);
sView.setHorizontalScrollBarEnabled(false);
so that scroll bar is not enabled on button click
Upvotes: -6
Reputation: 51
Here is a simpler solution. Override the onTouch()
for the ScrollView
OnTouchListener
and return false if you want to bypass the scroll by touch. The programmatic scrolling still works and no need to extend the ScrollView
class.
mScroller.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return isScrollable;
}
});
Upvotes: 3
Reputation: 11
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
// if we can scroll pass the event to the superclass
if (mScrollable) return super.onInterceptTouchEvent(ev);
// only continue to handle the touch event if scrolling enabled
return mScrollable; // mScrollable is always false at this point
default:
return super.onInterceptTouchEvent(ev);
}
}
Upvotes: 1
Reputation: 11926
Does this help?
((ScrollView)findViewById(R.id.QuranGalleryScrollView)).setOnTouchListener(null);
Upvotes: 0
Reputation:
As you can see in the documentation, you cannot set the visibility to false. In your case you should probably use:
scrollview.setVisibility(Visibility.GONE);
Upvotes: -7