LoginSignup
24
19

More than 5 years have passed since last update.

ScrollViewで最下部までスクロールしたときに処理を実行する

Last updated at Posted at 2013-07-03

AndroidのScrollViewで、最下部までスクロールしたときに自動的に続きを読み込むなどの処理を実行したかったため、ScrollViewを継承して、最下部にスクロールしたイベントを検知できる独自クラスを作成しました。

ListViewでも同じようなことができますが、何らかの理由でListViewは使えないときのために。

MyScrollView.java
package sample.hara.myscrollview;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ScrollView;

public class MyScrollView extends ScrollView {

    public interface ScrollToBottomListener {
        void onScrollToBottom(MyScrollView scrollView);
    }

    private ScrollToBottomListener scrollToBottomListener;
    private int scrollBottomMargin = 0;

    public MyScrollView(Context context) {
        super(context);
    }

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

    public MyScrollView(Context context, AttributeSet attrs, int defs) {
        super(context, attrs, defs);
    }

    public void setScrollToBottomListener(ScrollToBottomListener listener) {
        this.scrollToBottomListener = listener;
    }

    public void setScrollBottomMargin(int value) {
        this.scrollBottomMargin = value;
    }

    @Override
    protected void onScrollChanged(int x, int y, int oldx, int oldy) {
        super.onScrollChanged(x, y, oldx, oldy);
        View content = getChildAt(0);
        if (scrollToBottomListener == null) return;
        if (content == null) return;
        if (y + this.getHeight() >= content.getHeight() - scrollBottomMargin) {
            scrollToBottomListener.onScrollToBottom(this);
        }
    }
}

レイアウトxmlファイルからでも使用できます。

setScrollBottomMargin(int)メソッドにより、最下部より指定したピクセル数だけ手前までスクロールしたときにイベントを走らせることもできます。
たとえば、ScrollView最下部にある何らかのviewが表示される領域までスクロールされたときに処理を行うならば、setScrollBottomMargin(view.getHeight())のように指定しておけばOKです。

利用例

res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<sample.hara.myscrollview.MyScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <LinearLayout android:id="@+id/content"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
        </LinearLayout>

        <ProgressBar android:id="@+id/bottomView"
            android:layout_gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>

</sample.hara.myscrollview.MyScrollView>
MyScrollViewSampleActivity.java
package sample.hara.myscrollview;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MyScrollViewSampleActivity extends Activity {

    private static final int MAX = 500;

    private MyScrollView scroll;
    private View bottomView;
    private LinearLayout layout;
    private int count;
    private ReadMoreTask readMoreTask;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        scroll = (MyScrollView) LayoutInflater.from(this).inflate(R.layout.main, null);
        setContentView(scroll);
        layout = (LinearLayout) scroll.findViewById(R.id.content);
        bottomView = scroll.findViewById(R.id.bottomView);
        for(count = 0; count < 50; count++) {
            TextView tv = new TextView(this);
            tv.setText(count + "");
            layout.addView(tv);
        }

        scroll.setScrollToBottomListener(new MyScrollView.ScrollToBottomListener() {
            @Override
            public void onScrollToBottom(MyScrollView scrollView) {
                if (count >= MAX) return;
                if (readMoreTask != null) return;
                readMoreTask = new ReadMoreTask();
                readMoreTask.execute();
            }

        });
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        scroll.setScrollBottomMargin(bottomView.getHeight());
    }

    private class ReadMoreTask extends AsyncTask<Void, Void, Void> {

        @Override
        protected Void doInBackground(Void... params) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            }
            return null;
        }


        @Override
        protected void onPostExecute(Void result) {
            for (int i = 0; i < 50; i++) {
                TextView tv = new TextView(MyScrollViewSampleActivity.this);
                tv.setText(count + i + "");
                layout.addView(tv);
            }
            count += 50;
            if (count >= MAX) bottomView.setVisibility(View.GONE);
            readMoreTask = null;
        }
    };
}
24
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
19