Tắt ScrollView có lập trình?


108

Tôi muốn bật ScrollView và vô hiệu hóa nó bằng một Nhấp chuột.
Tắt có nghĩa là nếu ScrollView không có ở đó .. và bật nó sẽ trả về ScrollView.

Tôi muốn điều đó vì tôi có một thư viện với các hình ảnh văn bản và trên một nút bấm, hướng màn hình sẽ thay đổi, vì vậy trong Khổ ngang, văn bản trở nên lớn hơn. Và tôi muốn ScrollView để hình ảnh không tự giãn ra và văn bản trở nên không thể đọc được.

scrollview.Enabled=false / setVisibility(false) không làm bất cứ điều gì.

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>

Cảm ơn

Chỉnh sửa1: Tôi không thể sử dụng Chế độ hiển thị (đã biến mất) vì điều đó cũng sẽ ẩn Thư viện, điều tôi muốn là ẩn hiệu ứng của Chế độ xem cuộn. Khi có ScrollView, hình ảnh trong Thư viện sẽ trở thành bảng cuộn và không vừa với màn hình nên bạn phải cuộn để xem toàn bộ hình ảnh, tôi không muốn tắt / bật tính năng đó chỉ bằng một lần nhấp vào nút.

Tôi đã thử điều này:

((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);

Nhưng hình ảnh trong Thư viện vẫn có thể cuộn được và không vừa với màn hình .. giải pháp cho việc này là gì?

Câu trả lời:


187

Một số điểm để bắt đầu:

  1. Bạn không thể tắt tính năng cuộn ScrollView. Bạn sẽ cần mở rộng sang ScrollView và ghi đè onTouchEventphương thức để trả về falsekhi một số điều kiện được khớp.
  2. Thành phần Thư viện cuộn theo chiều ngang bất kể nó có nằm trong ScrollView hay không - ScrollView chỉ cung cấp chức năng cuộn theo chiều dọc (bạn cần có HorizontalScrollView để cuộn theo chiều ngang)
  3. Dường như bạn nói rằng bạn gặp vấn đề với việc tự kéo giãn hình ảnh - điều này không liên quan gì đến ScrollView, bạn có thể thay đổi cách ImageView mở rộng quy mô bằng thuộc android:scaleTypetính (XML) hoặc setScaleTypephương thức - ví dụ: ScaleType.CENTERsẽ không kéo dài hình ảnh của bạn và sẽ căn giữa nó ở kích thước ban đầu

Bạn có thể sửa đổi ScrollViewnhư sau để tắt tính năng cuộn

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);
    }

}

Sau đó bạn sẽ sử dụng

<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>

trong tệp XML của bạn (vừa thay đổi thành ScrollViewđặc biệt của bạn LockableScrollView).

Sau đó gọi

((LockableScrollView)findViewById(R.id.QuranGalleryScrollView)).setScrollingEnabled(false);

để tắt cuộn chế độ xem.

Tôi nghĩ rằng bạn không chỉ có vấn đề về việc tắt cuộn để đạt được kết quả mong muốn (ví dụ: thư viện sẽ vẫn có thể cuộn được với đoạn mã trên) - Tôi khuyên bạn nên thực hiện thêm một số nghiên cứu về từng thành phần trong số ba thành phần (Thư viện, ScrollView, ImageView) để xem mỗi cái có thuộc tính gì và hoạt động như thế nào.


Đây là cách lớp trông như thế nào: pastebin.com/dsWSWR4x Nhưng tôi gặp lỗi 'Phương thức onTouch (View, MotionEvent) của loại LockableScrollView phải ghi đè hoặc triển khai phương thức siêu kiểu'
Omar

Xin lỗi, đã sửa các lỗi trong mã của tôi - lẽ ra phải như vậyonTouchEvent(MotionEvent ev)
Joseph Earl

1
Ok, bây giờ mã tuân thủ, mặc dù khi tôi chạy ứng dụng, nó bị lỗi ... và khi tôi xóa lớp này và trả lại <ScrollView thay vì lớp của bạn, ứng dụng hoạt động tốt!
Omar

Chào Omar, bạn có thể đăng lỗi mà bạn gặp phải không? Hãy chắc chắn rằng sự thay đổi các com.mypackagename trong <com.mypackagename.LockableScrollView> để một mình
Joseph Earl

1
Câu trả lời tốt. Nếu bạn thay đổi trường hợp MotionEvent.ACTION_DOWN: thành trường hợp MotionEvent.ACTION_MOVE: trường hợp MotionEvent.ACTION_DOWN: bạn cũng sẽ có thể tắt cuộn trong khi kéo. Nhưng tất nhiên là mọi người cần sử dụng nó như thế nào.
luky

70

Tôi đã đi theo cách này:

        scrollView.setOnTouchListener(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            return isBlockedScrollView;
        }
    });

3
Đơn giản và hoạt động tuyệt vời. Điểm mấu chốt là sử dụng một biến (ví dụ: isBlockedScrollView) để kiểm soát khi bạn muốn bật tính năng cuộn. Đặt nó thành true khi cho phép cuộn và ngược lại là false.
PeteH

5
@PeteH, tôi không biết tại sao, nhưng của tôi ListViewhoạt động theo cách ngược lại: true khi cuộn bị tắt và false khi nó được bật.
Machado

@Holmes: bạn là đúng, đúng khi bạn muốn chặn di chuyển
lily

1
Ngoài ra, tôi có các chế độ xem (nút) con trong chế độ xem cuộn và tôi vẫn có thể tương tác với chúng mặc dù không ghi đè onInterceptTouchEvent ()! Giải pháp thanh lịch.
Cody

1
@Machado Lý do bạn phải trả về true để chặn cuộn là vì trình xử lý cảm ứng nhận giá trị boolean được trả về để xác định xem có nên sử dụng sự kiện cảm ứng hay không. Nếu bạn trả về false, chế độ xem cuộn sẽ tiếp tục chuyển sự kiện chạm tới trình nghe cuộn của nó.
Vince

11

Đã tìm thấy giải pháp đơn giản này vừa được thiết lập

ScrollView.requestDisallowInterceptTouchEvent(true);

5
requestDisallowInterceptTouchEventchỉ hoạt động đối với con của Chế độ xem được khóa. Vì vậy, nó sẽ giống như vậymLinearLayout.requestDisallowInterceptTouchEvent(true);
Muz

6

Tắt ScrollView

ScrollView sw = (ScrollView) findViewById(R.id.scrollView1);
sw.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return true;
    }
});

5

để bắt đầu, tôi đã sử dụng Mã được đăng trong Bình luận đầu tiên nhưng tôi đã thay đổi nó như thế này:

    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);      
            }
    }

}

sau đó tôi gọi nó bằng cách này

((LockableScrollView)findViewById(R.id.scrollV)).setScrollingEnabled(false);

bởi vì tôi đã cố gắng

((LockableScrollView)findViewById(R.id.scrollV)).setIsScrollable(false);

nhưng nó nói rằng setIsScrollable là không xác định

Tôi hy vọng điều này sẽ giúp bạn


Lưu ý: hai hàm tạo đầu tiên là cần thiết nếu bạn ScrollViewlà vùng chứa bố cục chính của lớp bố trí của bạn.
actaram

Nếu bạn chạm vào một nút hoặc một cái gì đó khác mà đánh chặn các chạm đầu tiên, scrollview sẽ vẫn cuộn
Cristi Băluţă

3

Đây là một giải pháp đơn giản hơn. Ghi đè onTouch()cho ScrollView OnTouchListenervà trả về false nếu bạn muốn bỏ qua cuộn bằng cách chạm. Thao tác cuộn theo chương trình vẫn hoạt động và không cần mở rộng ScrollViewlớp.

mScroller.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
  return isScrollable;
}
});

1
! isScrollable vì giá trị trả về true có nghĩa là sự kiện đã bị chặn.
goRGon

3

Tôi không có đủ điểm để nhận xét về một câu trả lời, nhưng tôi muốn nói rằng câu trả lời của mikec phù hợp với tôi ngoại trừ việc tôi phải thay đổi nó để quay lại! IsScrollable như vậy:

mScroller.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
      return !isScrollable;
    }
});

1
@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);      
            }
    }

1

@JosephEarl +1 Anh ấy có một giải pháp tuyệt vời ở đây phù hợp hoàn hảo với tôi với một số sửa đổi nhỏ để thực hiện nó theo chương trình.


Dưới đây là những thay đổi nhỏ mà tôi đã thực hiện:

Lớp LockableScrollView:

public boolean setScrollingEnabled(boolean enabled) {
    mScrollable = enabled;
    return mScrollable;
}

Hoạt động chủ yêu:

LockableScrollView sv;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    sv = new LockableScrollView(this);
    sv.setScrollingEnabled(false);
}

1

Tôi đã có một bố cục trên NestedScrollView sử dụng sự kiện chạm và vô hiệu hóa cuộn:

progressBarLayout.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                return true;
            }
        });

và để kích hoạt:

progressBarLayout.setOnTouchListener(null);

1

Bạn có thể tạo một CustomScrollView, mà bạn có thể vô hiệu hóa sự can thiệp của nó với các chế độ xem khác. Mặc dù điều này đôi khi có thể gây khó chịu cho người dùng cuối. Sử dụng nó một cách thận trọng.

Đây là mã:

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;
    }
}

Làm cách nào để sử dụng CustomScrollView?

Bạn có thể thêm CustomScrollView làm cha mẹ vào màn hình mà bạn muốn thêm một Scrollview khác làm chế độ xem con và toàn bộ màn hình có thể cuộn được. Tôi đã sử dụng cái này cho một 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>

Nó đã làm việc cho trường hợp của tôi.


1
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);
    }
}

0

Không giúp đỡ à?

((ScrollView)findViewById(R.id.QuranGalleryScrollView)).setOnTouchListener(null);

1
Tôi không nghĩ rằng nó đã làm bất kỳ sự khác biệt nào, tôi vẫn gặp phải vấn đề tương tự
Omar

0

Bạn có thể mở rộng thư viện và sử dụng một số cờ để tắt cuộn khi bạn muốn:

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;
}
}

-3

Như bạn có thể thấy trong tài liệu , bạn không thể đặt khả năng hiển thị thành false. Trong trường hợp của bạn, bạn có thể nên sử dụng:

scrollview.setVisibility(Visibility.GONE);

2
Điều này cũng sẽ ẩn Thư viện để nó không phải là giải pháp, tôi đã chỉnh sửa bài đăng với nhiều chi tiết hơn
Omar

-6

trên nút bấm người nghe chỉ cần làm

ScrollView sView = (ScrollView)findViewById(R.id.ScrollView01);

sView.setVerticalScrollBarEnabled(false);
sView.setHorizontalScrollBarEnabled(false);

để thanh cuộn không được bật khi nhấp vào nút


2
Điều này chỉ ẩn các thanh mà tôi đoán .. nhưng không phải ảnh hưởng của chế độ xem cuộn
Omar

1
nó sẽ không cho phép bạn cuộn nó cũng sẽ không ẩn chế độ xem thư viện
Sumant
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.