88

を使用するアクティビティを持つアプリがありScrollViewます。ユーザーがいつ下に到達したかを検出する必要がありますScrollViewグーグルで検索したところ、説明されているこのページが見つかりました。しかし、この例では、その男は拡張しScrollViewます。私が言ったように、Activity を拡張する必要があります。

ScrollViewそれで、「よし、カスタム クラスを拡張して、メソッドをオーバーライドしonScrollChanged()、スクロールの終わりを検出し、それに応じて動作するようにしよう」と言いました。

私はしましたが、この行で:

scroll = (ScrollViewExt) findViewById(R.id.scrollView1);

をスローし java.lang.ClassCastExceptionます。XMLのタグを変更しました<ScrollView>が、明らかに機能しません。私の質問は次のとおりです。なぜ、ScrollViewExtextendsScrollViewの場合、私の顔に a をスローするのClassCastExceptionですか? あまりいじらずにスクロールの終わりを検出する方法はありますか?

ありがとうございます。

編集:約束どおり、ここに重要な XML の一部があります。

<ScrollView
        android:id="@+id/scrollView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >


        <WebView
            android:id="@+id/textterms"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center_horizontal"
            android:textColor="@android:color/black" />

    </ScrollView>

中のテキストを正当化できるようにからTextViewに変更しました。WebView私が達成したいのは、「契約条件が完全に読まれるまで同意ボタンがアクティブにならない」ということです。私の拡張クラスはScrollViewExt と呼ばれます。タグScrollViewを変更するScrollViewExtと、

android.view.InflateException: Binary XML file line #44: Error inflating class ScrollViewExt

タグを理解していないためScrollViewExです。解決策はないと思います...

回答ありがとうございます。

4

13 に答える 13

114

それをやった!

Alexandre が親切に提供してくれた修正とは別に、インターフェイスを作成する必要がありました。

public interface ScrollViewListener {
    void onScrollChanged(ScrollViewExt scrollView, 
                         int x, int y, int oldx, int oldy);
}

次に、ScrollViewExt の ScrollView から OnScrollChanged メソッドをオーバーライドする必要がありました。

public class ScrollViewExt extends ScrollView {
    private ScrollViewListener scrollViewListener = null;
    public ScrollViewExt(Context context) {
        super(context);
    }

    public ScrollViewExt(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public ScrollViewExt(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setScrollViewListener(ScrollViewListener scrollViewListener) {
        this.scrollViewListener = scrollViewListener;
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (scrollViewListener != null) {
            scrollViewListener.onScrollChanged(this, l, t, oldl, oldt);
        }
    }
}

さて、Alexandre が言ったように、パッケージ名を XML タグに入れ (私のせいです)、以前に作成したインターフェイスを Activity クラスに実装させてから、すべてをまとめます。

scroll = (ScrollViewExt) findViewById(R.id.scrollView1);
scroll.setScrollViewListener(this);

メソッド OnScrollChanged では、インターフェースから...

@Override
public void onScrollChanged(ScrollViewExt scrollView, int x, int y, int oldx, int oldy) {
    // We take the last son in the scrollview
    View view = (View) scrollView.getChildAt(scrollView.getChildCount() - 1);
    int diff = (view.getBottom() - (scrollView.getHeight() + scrollView.getScrollY()));

    // if diff is zero, then the bottom has been reached
    if (diff == 0) {
        // do stuff
    }
}

そしてそれは働いた!

助けてくれてありがとう、アレクサンドル!

于 2012-04-26T13:23:06.200 に答える
96

これを検出する簡単な方法を見つけました:

   scrollView.getViewTreeObserver()
       .addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
            @Override
            public void onScrollChanged() {
                if (scrollView.getChildAt(0).getBottom()
                     <= (scrollView.getHeight() + scrollView.getScrollY())) {
                    //scroll view is at bottom
                } else {
                    //scroll view is not at bottom
                }
            }
        });
  • ScrollView をカスタムする必要はありません。
  • Scrollview は直接の子を 1 つしかホストできないため、scrollView.getChildAt(0)は問題ありません。
  • この解決策は、スクロール ビューの直接の子の高さがmatch_parentまたはwrap_contentであっても正しいです。
于 2016-12-14T10:00:50.550 に答える
10

編集

XMLの内容から、ScrollViewを使用していることがわかります。カスタムビューを使用する場合は、com.your.packagename.ScrollViewExtと記述する必要があります。これにより、コードで使用できるようになります。

<com.your.packagename.ScrollViewExt
    android:id="@+id/scrollView1"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <WebView
        android:id="@+id/textterms"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal"
        android:textColor="@android:color/black" />

</com.your.packagename.ScrollViewExt>

編集終了

xmlコンテンツを投稿してもらえますか?

スクロールリスナーを追加して、最後に表示されたアイテムがリストビューの最後のアイテムであるかどうかを確認するだけでよいと思います。

mListView.setOnScrollListener(new OnScrollListener() {      
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        // TODO Auto-generated method stub      
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        // TODO Auto-generated method stub
        if(view.getLastVisiblePosition()==(totalItemCount-1)){
            //dosomething
        }
    }
});
于 2012-04-25T13:41:03.010 に答える
5

サポート ライブラリNestedScrollViewとそのNestedScrollView.OnScrollChangeListenerインターフェイスを利用できます。

https://developer.android.com/reference/android/support/v4/widget/NestedScrollView.html

または、アプリが API 23 以降をターゲットにしている場合は、次のメソッドを で使用できますScrollView

View.setOnScrollChangeListener(OnScrollChangeListener listener) 

次に、@Fustigador が回答で説明した例に従います。ただし、@Will が説明したように、ユーザーまたはシステムが何らかの理由でリストの最後に完全に到達できない場合に備えて、小さなバッファーを追加することを検討する必要があります。

また、スクロール変更リスナーは、負の値またはビューの高さより大きい値で呼び出される場合があることにも注意してください。おそらく、これらの値はスクロール アクションの「勢い」を表しています。ただし、適切に処理しないと (floor / abs)、ビューが範囲の上部または下部にスクロールされたときにスクロール方向を検出する際に問題が発生する可能性があります。

https://developer.android.com/reference/android/view/View.html#setOnScrollChangeListener(android.view.View.OnScrollChangeListener)

于 2016-10-07T02:35:05.003 に答える
4

scrollView.getPaddingBottom()スクロール ビューの xml ファイルにパディングがある場合があるため、スクロール ビューの高さ全体に一致するように常に追加する必要があります。

scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
        @Override
        public void onScrollChanged() {
            if (scrollView != null) {
               View view = scrollView.getChildAt(scrollView.getChildCount()-1);
               int diff = (view.getBottom()+scrollView.getPaddingBottom()-(scrollView.getHeight()+scrollView.getScrollY()));

          // if diff is zero, then the bottom has been reached
               if (diff == 0) {
               // do stuff
                }
            }
        }
    });
于 2016-12-20T17:33:30.733 に答える
4

インターネットで解決策を調べました。ほとんどのソリューションは、私が取り組んでいるプロジェクトでは機能しませんでした。次の解決策は私にとってはうまくいきます。

onScrollChangeListener の使用 (API 23 で動作):

   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        scrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
            @Override
            public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {

                int bottom =   (scrollView.getChildAt(scrollView.getChildCount() - 1)).getHeight()-scrollView.getHeight()-scrollY;

                if(scrollY==0){
                    //top detected
                }
                if(bottom==0){
                    //bottom detected
                }
            }
        });
    }

TreeObserver で scrollChangeListener を使用する

 scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
        @Override
        public void onScrollChanged() {
            int bottom =   (scrollView.getChildAt(scrollView.getChildCount() - 1)).getHeight()-scrollView.getHeight()-scrollView.getScrollY();

            if(scrollView.getScrollY()==0){
                //top detected
            }
            if(bottom==0) {
                //bottom detected
            }
        }
    });

このソリューションが役立つことを願っています:)

于 2020-07-07T04:53:33.920 に答える
2

カスタムの最後にいるかどうかを判断するにはScrollView、メンバー変数を使用して最後の y 位置を保存することもできます。次に、最後の y 位置と現在のスクロール位置を比較できます。

private int scrollViewPos;

...

@Override
public void onScrollChanged(ScrollViewExt scrollView, int x, int y, int oldx, int oldy) {

   //reached end of scrollview
   if (y > 0 && scrollViewPos == y){
      //do something
   }

   scrollViewPos = y;
}
于 2014-07-03T13:58:55.240 に答える