2

Horizo​​ntalScrollView から無限ページャーを作成しようとしています。

必要に応じて子ビューを継続的に再配置することで無限にスクロールしますが、ビューの移動 (左または右への追加) を開始する必要があると、スムーズにスクロールしなくなります。子の位置を変更した後でも、スムーズに次のページにスクロールする方法を見つけようとしています。

これまでのクラスは次のとおりです。

import java.util.HashMap;
import java.util.Map;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;

public class PagerInfinite extends HorizontalScrollView {
    private LinearLayout contents;
    private Map<Integer, Integer> childWidths =  new HashMap<Integer, Integer>();
    private int childSpacing = 0;
    private int activePageIndex = 1;
    private float oldX = 0f;
    private float oldY = 0f;
    private boolean firstScroll = true;

public PagerInfinite(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.contents = new LinearLayout(context);
    this.contents.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT));
    this.addView(this.contents);
    setVerticalScrollBarEnabled(false);
    setHorizontalScrollBarEnabled(false);
}

@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    for (int i = 0; i < this.contents.getChildCount(); i++) {
        View child = this.contents.getChildAt(i);
        int width = child.getWidth();
        if(width != 0) {
            this.childWidths.put(i, width);
        }
    }
    if(this.childWidths.size() > 0 && this.firstScroll) {
        this.smoothScrollTo(this.getActivePageOffset(), 0);
        this.firstScroll = false;
    }
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

@Override
protected float getLeftFadingEdgeStrength() {
    return 0.0f;
}

@Override
protected float getRightFadingEdgeStrength() {
    return 0.0f;
}

public void addPage(View child) {
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    params.setMargins(0, 0, this.childSpacing, 0);
    child.setLayoutParams(params);
    if(this.contents.getChildCount() <= 1) {
        this.contents.addView(child);
    } else if(this.contents.getChildCount() <= 2) {
        this.contents.addView(child, 0);
    } else {
        View last = this.contents.getChildAt(0);
        this.contents.removeView(last);
        this.contents.addView(last);
        this.contents.addView(child, 0);
    }
    this.contents.requestLayout();
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    boolean result = super.onTouchEvent(event);

    switch(event.getAction()) {
        case(MotionEvent.ACTION_DOWN):
            this.oldX = event.getX();
            this.oldY = event.getY();
            break;
        case(MotionEvent.ACTION_UP):
            float newX = event.getX();
            float newY = event.getY();
            float deltaX = newX - this.oldX;
            float deltaY = newY - this.oldY;

            // Use deltaX and deltaY to determine the direction
            if(Math.abs(deltaX) > Math.abs(deltaY)) {
                if(deltaX > 0) {
                    // right
                    if(this.activePageIndex <= 1) {
                        this.buildLeft();
                    } else {
                        this.activePageIndex -= 1;
                    }
                } else {
                    // left
                    if(this.activePageIndex >= this.contents.getChildCount() - 2) {
                        this.buildRight();
                    } else {
                        this.activePageIndex += 1;
                    }
                }
            }
            this.smoothScrollTo(this.getActivePageOffset(), 0);
            break;
    }

    return result;
}

private void buildLeft() {
    View view = this.contents.getChildAt(this.contents.getChildCount() - 1);
    this.contents.removeView(view);
    this.contents.addView(view, 0);
}

private void buildRight() {
    View view = this.contents.getChildAt(0);
    this.contents.removeView(view);
    this.contents.addView(view);
}

private int getActivePageOffset() {
    Log.d(LCHApplication.TAG, "ActiveIndex = " + this.activePageIndex);
    if(this.activePageIndex == 0) {
        return 0;
    }
    if(this.activePageIndex == this.contents.getChildCount() - 1) {
        return this.contents.getWidth();
    }
    int offset = 0;
    for(Map.Entry<Integer, Integer> entry : this.childWidths.entrySet()) {
        if(entry.getKey() < this.activePageIndex) {
            offset += entry.getValue() + this.childSpacing;
        } else {
            break;
        }
    }
    offset += (this.childWidths.get(this.activePageIndex) / 2);
    offset -= (LCHApplication.instance.width / 2);
    return offset;
}

public boolean hasPage(View v) {
    return this.contents.indexOfChild(v) != -1;
}

public void removePage(View v) {
    int index = this.contents.indexOfChild(v);
    this.contents.removeView(v);
    this.childWidths.remove(index);
}

public int getCurrentPageIndex() {
    return this.activePageIndex;
}

public int getPageCount() {
    return this.contents.getChildCount();
}

public void removeAllPages() {
    this.contents.removeAllViews();
    this.childWidths = new HashMap<Integer, Integer>();
}

public void cycle() {
    if(this.activePageIndex < this.contents.getChildCount() - 1) {
        this.activePageIndex += 1;
    } else {
        this.activePageIndex = 0;
    }
    this.smoothScrollTo(this.getActivePageOffset(), 0);
}

public int getChildSpacing() {
    return this.childSpacing;
}

public void setChildSpacing(int spacing) {
    this.childSpacing = spacing;
}
}
4

1 に答える 1

0

手遅れですが、同じ問題を抱えている他の誰かに私の答えが役立つと思います。

無限ページのサンプル プロジェクト - ページ スワイプ効果あり

https://github.com/UdaySravanK/USK_APIs

于 2014-08-12T10:36:59.230 に答える