プログラムでScrollViewを無効にしますか?


108

ScrollViewを有効にし、ボタンのクリックで無効にします。
無効とは、ScrollViewがそこになかった場合と同様です。有効にすると、ScrollViewが返されます。

テキスト画像のギャラリーがあり、ボタンをクリックすると画面の向きが変わるため、横向きではテキストが大きくなるので、それが必要です。そして、ScrollViewが欲しいので、画像がそれ自体を引き伸ばさず、テキストが読めなくなります。

scrollview.Enabled=false / setVisibility(false) 何もしません。

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>

ありがとう

Edit1:Visibility(gone)を使用することはできません。これはギャラリーも非表示にするため、ScrollViewの効果を非表示にすることです。ScrollViewがある場合、ギャラリー内の画像はスクロール可能になり、画面に収まらないため、画像全体を表示するためにスクロールする必要があります。ボタンのクリックで無効/有効にしたくありません。

私はこれを試しました:

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

しかし、それでもギャラリー内の画像はスクロール可能であり、画面に適合しません。これに対する解決策は何ですか?

回答:


187

最初にいくつかのポイント:

  1. ScrollViewのスクロールを無効にすることはできません。ScrollViewに拡張し、いくつかの条件が一致したときにonTouchEventメソッドをオーバーライドして返す必要がありますfalse
  2. Galleryコンポーネントは、ScrollViewにあるかどうかに関係なく水平方向にスクロールします-ScrollViewは垂直スクロールのみを提供します(水平スクロールにはHorizo​​ntalScrollViewが必要です)
  3. 画像自体に問題があるとおっしゃっているようです-これはScrollViewとは関係なく、ImageViewがandroid:scaleTypeプロパティ(XML)またはsetScaleTypeメソッドを使用してスケーリングする方法を変更できます。たとえばScaleType.CENTER、画像を拡大しないため、元のサイズに合わせます

ScrollView次のように変更して、スクロールを無効にすることができます

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

}

次に使用します

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

あなたのXMLファイルで(ScrollViewあなたの特別なに変更しただけですLockableScrollView

次に電話します

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

ビューのスクロールを無効にします。

望ましい結果を達成するためにスクロールを無効にするだけの問題があると思います(たとえば、ギャラリーは上記のコードでスクロール可能のままになります)-3つの各コンポーネント(ギャラリー、 ScrollView、ImageView)を使用して、各プロパティのプロパティとその動作を確認します。


:ここではどのようにクラスのルックスでpastebin.com/dsWSWR4x しかし、私はエラー「上書きしたり、スーパータイプのメソッドを実装する必要がありますタイプLockableScrollViewの方法onTouch(ビュー、MotionEvent)」を得る
オマール

謝罪、私のコードのエラーを修正しました-本来あるべきだったのですonTouchEvent(MotionEvent ev)
ジョセフ・アール

1
さて、コードは準拠していますが、アプリを実行するとクラッシュします...このクラスを削除して、クラスの代わりに<ScrollViewを返すと、アプリは正常に動作します!
Omar

こんにちはオマールあなたが得るエラーを投稿できますか?<com.mypackagename.LockableScrollView>のcom.mypackagenameを独自のものに変更してください
Joseph Earl

1
いい答えだ。case MotionEvent.ACTION_DOWN:をcase MotionEvent.ACTION_MOVE:case MotionEvent.ACTION_DOWN:に変更すると、ドラッグ中もスクロールを無効にすることができます。もちろん、彼がそれをどのように使用する必要があるかは、誰にとっても当然です。
16年

70

私はこのように行きました:

        scrollView.setOnTouchListener(new View.OnTouchListener() {

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

3
シンプルで素晴らしい作品。重要な点は、変数(isBlockedScrollViewなど)を使用して、スクロールを有効にするタイミングを制御することです。スクロールを許可する場合はtrueに、そうでない場合はfalseに設定します。
PeteH 2014

5
@PeteH、理由はわかりませんが、ListView逆の方法で機能します。スクロールが無効の場合はtrue、有効の場合はfalse
マチャド

@ホームズ:あなたは正しい、スクロールをブロックしたいときに真実
リリー

1
美しく動作します。また、スクロールビュー内に子ビュー(ボタン)があり、onInterceptTouchEvent()をオーバーライドしていなくても、子ビューと対話できます。エレガントなソリューション。
Cody

1
@Machadoスクロールをブロックするためにtrueを返さなければならない理由は、タッチリスナーが、返されたブール値を取得して、タッチイベントを消費するかどうかを決定するためです。falseを返すと、スクロールビューはタッチイベントをスクロールリスナーに渡します。
ビンス

11

設定されたこのシンプルなソリューションが見つかりました

ScrollView.requestDisallowInterceptTouchEvent(true);

5
requestDisallowInterceptTouchEventロックされるビューのに対してのみ機能します。それはより多くのようになるのでmLinearLayout.requestDisallowInterceptTouchEvent(true);
MUZ

6

Disablend ScrollView

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

5

まず、最初のコメントに投稿されたコードを使用しましたが、次のように変更しました。

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

}

それから私はこの方法でそれを呼び出しました

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

私が試したので

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

しかし、それはsetIsScrollableが未定義であると述べました

これがお役に立てば幸いです


注:がScrollViewレイアウトクラスのメインレイアウトコンテナーである場合、最初の2つのコンストラクターが必要です。
アクタラム2015

最初にタッチをインターセプトするボタンなどにタッチしても、スクロールビューはスクロールします
Cristi Băluță

3

これがより簡単な解決策です。タッチでスクロールをバイパスする場合onTouch()は、forをオーバーライドしてScrollView OnTouchListenerfalseを返します。プログラムによるスクロールは引き続き機能し、ScrollViewクラスを拡張する必要はありません。

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

1
!isScrollableは、trueの戻り値はイベントがインターセプトされたことを意味します。
goRGon 2016年

3

回答にコメントするのに十分なポイントはありませんが、mikecの回答は私にとってはうまくいったと言いたかったのですが、次のように!isScrollableを返すように変更する必要がありました。

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彼はここで、プログラムでそれを行うためのいくつかのマイナーな変更で完璧に機能する素晴らしいソリューションを持っています。


ここに私が行った小さな変更があります:

LockableScrollViewクラス:

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

主な活動:

LockableScrollView sv;

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

1

NestedScrollViewのレイアウトでtouchイベントを消費し、スクロールを無効にしました。

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

有効にするには:

progressBarLayout.setOnTouchListener(null);

1

CustomScrollViewを作成して、他のビューとの干渉を無効にすることができます。ただし、これはエンドユーザーにとって不快な場合があります。注意して使用してください。

これはコードです:

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

CustomScrollViewの使用方法

CustomScrollViewを、別のScrollviewを子ビューとして追加する画面の親として追加できます。画面全体がスクロール可能です。これを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>

私の場合はうまくいきました。


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

これは役に立ちますか?

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

1
私はそれがどんな違いをしたとは思わない、私はまだ同じ問題を抱えている
Omar

0

必要に応じて、ギャラリーを拡張し、いくつかのフラグを使用してスクロールを無効にすることができます。

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

ドキュメントでわかるように、可視性をfalseに設定することはできません。あなたの場合、おそらく以下を使用する必要があります:

scrollview.setVisibility(Visibility.GONE);

2
これによりギャラリーも非表示になるため、解決策ではありません。詳細を追加して投稿を編集しました
Omar

-6

ボタンをクリックしたリスナーで

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

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

ボタンをクリックしたときにスクロールバーが有効にならないようにする


2
これは私が推測するバーが非表示になります..しかしないscrollviewの効果
オマール

1
スクロールできません。また、ギャラリービューも非表示になりません
Sumant
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.