1. 程式人生 > >Android 實現無限滾動的ScrollView

Android 實現無限滾動的ScrollView

用ScrollView實現類似 新聞頭條或廣告圖的無限滾動

效果:


思路是在看智慧社的JavaScript相關視訊時候想到的,具體就是講動畫那個節,實現圖片的無縫滾動

在這裡就不講了(主要是講也講不明白==)

本來是直接寫在Activity裡面,後面為了複用,直接封裝成一個EndlessScrollView類和EndlessHorizontalScrollView類

其中EndlessScrollView類向外暴露一個setData方法,用於設定相應的文字資料。

而EndlessHorizontalScrollView類則暴露了setTextData()和setImageData()兩個方法,用於設定文字和圖片資料

上原始碼:

EndlessScrollView.java

package com.example.jp04.myapplication.views;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.widget.LinearLayout;
import 
android.widget.ScrollView; import android.widget.TextView; import com.example.jp04.myapplication.R; import com.example.jp04.myapplication.utils.Utils; import java.util.List; /** * 無限滾動的ScrollView(無縫滾動) * Created by jp04 on 2017/3/10. */ public class EndlessScrollView extends ScrollView { private LinearLayout llData
; private static final int MESSAGE_SCROLL = 10010; private static int offset = 1000; //滾動的時間間隔 private int pageSize, itemHeight, maxScrollHeight; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_SCROLL: int scrollY = getScrollY(); int delay = 0; if (scrollY >= maxScrollHeight) { scrollTo(0, 0); } else { smoothScrollBy(0, itemHeight); delay = offset; } postDelayed(new Runnable() { @Override public void run() { sendEmptyMessage(MESSAGE_SCROLL); } }, delay); break; } } }; public EndlessScrollView(Context context) { this(context, null); } public EndlessScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public EndlessScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init() { llData = new LinearLayout(getContext()); llData.setOrientation(LinearLayout.VERTICAL); llData.setLayoutParams(new ScrollView.LayoutParams(-1, -1)); addView(llData); } public void setData(final List<String> data, final int pageSize) { post(new Runnable() { @Override public void run() { int containerHeight = getMeasuredHeight(); EndlessScrollView.this.pageSize = pageSize; EndlessScrollView.this.itemHeight = containerHeight / pageSize; EndlessScrollView.this.maxScrollHeight = data.size() * itemHeight; data.addAll(data); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(-1, itemHeight); for (int i = 0; i < data.size(); i++) { TextView textView = new TextView(getContext()); textView.setTextColor(Utils.getColor(R.color.textcolor_normal)); textView.setGravity(Gravity.CENTER_VERTICAL); textView.setText(data.get(i)); textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14); llData.addView(textView, params); } handler.postDelayed(new Runnable() { @Override public void run() { handler.sendEmptyMessage(MESSAGE_SCROLL); } }, offset); } }); } }

EndlessHorizontalScrollView.java

package com.example.jp04.myapplication.views;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.example.jp04.myapplication.R;
import com.example.jp04.myapplication.utils.Utils;
import com.nostra13.universalimageloader.core.ImageLoader;
import java.util.List;
/**
 * 無限滾動的ScrollView(橫向)
 * Created by jp04 on 2017/3/10.
 */
public class EndlessHorizontalScrollView extends HorizontalScrollView {
    private LinearLayout llData;
    private static final int MESSAGE_SCROLL = 10010;
    private static int offset = 1000; //滾動的時間間隔
private int pageSize, itemWidth, maxScrollWidth;
    private Handler handler = new Handler() {
        @Override
public void handleMessage(Message msg) {
            switch (msg.what) {
                case MESSAGE_SCROLL:
                    int scrollX = getScrollX();
                    int delay = 0;
                    if (scrollX >= maxScrollWidth) {
                        scrollTo(0, 0);
} else {
                        smoothScrollBy(itemWidth, 0);
delay = offset;
}
                    postDelayed(new Runnable() {
                        @Override
public void run() {
                            sendEmptyMessage(MESSAGE_SCROLL);
}
                    }, delay);
                    break;
}
        }
    };
    public EndlessHorizontalScrollView(Context context) {
        this(context, null);
}

    public EndlessHorizontalScrollView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
}

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

    private void init() {
        llData = new LinearLayout(getContext());
llData.setOrientation(LinearLayout.HORIZONTAL);
llData.setLayoutParams(new LayoutParams(-1, -1));
addView(llData);
}

    public void setTextData(final List<String> data, final int pageSize) {

       post(new Runnable() {
           @Override
public void run() {
               int containerWidth = getMeasuredWidth();
EndlessHorizontalScrollView.this.pageSize = pageSize;
EndlessHorizontalScrollView.this.itemWidth = containerWidth / pageSize;
EndlessHorizontalScrollView.this.maxScrollWidth = data.size() * itemWidth;
data.addAll(data);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(itemWidth, -1);
               for (int i = 0; i < data.size(); i++) {
                   TextView textView = new TextView(getContext());
textView.setTextColor(Utils.getColor(R.color.textcolor_normal));
textView.setGravity(Gravity.CENTER_VERTICAL);
textView.setText(data.get(i));
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
llData.addView(textView, params);
}

               handler.postDelayed(new Runnable() {
                   @Override
public void run() {
                       handler.sendEmptyMessage(MESSAGE_SCROLL);
}
               }, offset);
}
       });
}

    public void setImageData(final List<String> data, final int pageSize) {

        post(new Runnable() {
            @Override
public void run() {
                int containerWidth = getMeasuredWidth();
EndlessHorizontalScrollView.this.pageSize = pageSize;
EndlessHorizontalScrollView.this.itemWidth = containerWidth / pageSize;
EndlessHorizontalScrollView.this.maxScrollWidth = data.size() * itemWidth;
data.addAll(data);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(itemWidth, -1);
                for (int i = 0; i < data.size(); i++) {
                    ImageView imageView = new ImageView(getContext());
String url = data.get(i);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
ImageLoader.getInstance().displayImage(url, imageView);
llData.addView(imageView, params);
}

                handler.postDelayed(new Runnable() {
                    @Override
public void run() {
                        handler.sendEmptyMessage(MESSAGE_SCROLL);
}
                }, offset);
}
        });
}

}

在相應的Activity中呼叫即可:

public class EndlessScrollViewActivity extends Activity {
    private EndlessScrollView esvNews;
    private EndlessHorizontalScrollView ehsvNews;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
setContentView(R.layout.activity_endless_scrollview);
esvNews = (EndlessScrollView) findViewById(R.id.esv_news);
ehsvNews = (EndlessHorizontalScrollView) findViewById(R.id.ehsv_news);
List<String> newsList = new ArrayList<>();
        for(int i = 0; i < 10; i++) {
            newsList.add(String.valueOf(i));
}
        esvNews.setData(newsList, 3);
List<String> imageUrls = new ArrayList<String>();
imageUrls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1489140233265&di=1dc81ca9048383fede008b8e6a8bf50b&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fforum%2Fpic%2Fitem%2F4d5e27ed2e738bd447fa9de5a18b87d6257ff972.jpg");
imageUrls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1489140245122&di=b5dc786d2e7379e637e3f07681d23ff7&imgtype=0&src=http%3A%2F%2Fa.hiphotos.baidu.com%2Fzhidao%2Fpic%2Fitem%2F72f082025aafa40f334b883fad64034f79f01946.jpg");
imageUrls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1489140258012&di=07b5d545dfb2b14d44112c35e8673de0&imgtype=0&src=http%3A%2F%2Fwww.qqzhi.com%2Fuploadpic%2F2014-05-14%2F061226958.jpg");
imageUrls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1489140849024&di=f32000dc7ac64e3140158cba302e32df&imgtype=0&src=http%3A%2F%2Ff0.topit.me%2F0%2F76%2F84%2F11545467533ed84760o.jpg");
imageUrls.add("https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2397520815,2843221100&fm=23&gp=0.jpg");
imageUrls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1489140884020&di=877664ad43c921f8ab7223b4b81315c4&imgtype=0&src=http%3A%2F%2Fc.hiphotos.baidu.com%2Fzhidao%2Fpic%2Fitem%2F6a600c338744ebf8f8b23843d9f9d72a6159a78f.jpg");
imageUrls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1489140896008&di=b6d5b655fc1ec7e72f70f4634be3d2de&imgtype=0&src=http%3A%2F%2Fimg2.a0bi.com%2Fupload%2Fttq%2F20160110%2F1452399200997.jpg");
imageUrls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1489140915014&di=b032ce6bf87cc092507328d562722a71&imgtype=0&src=http%3A%2F%2Fb.hiphotos.baidu.com%2Fzhidao%2Fpic%2Fitem%2F5bafa40f4bfbfbed0ac552ba79f0f736aec31f52.jpg");
ehsvNews.setImageData(imageUrls, 3);
}
}

佈局檔案:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
    <com.example.jp04.myapplication.views.EndlessHorizontalScrollView
android:layout_width="match_parent"
android:layout_height="80dp"
android:id="@+id/ehsv_news"/>
    <com.example.jp04.myapplication.views.EndlessScrollView
android:layout_margin="10dp"
android:layout_width="match_parent"
android:layout_height="60dp"
android:id="@+id/esv_news" />
</LinearLayout>