Android 自定义水平滚动的容器

public class HorizontalScrollView extends ViewGroup {
    //手势
    private GestureDetector mGestureDetector;

    private HorizontalScroller mScroller;
    private int curID;
    //快速滑动
    private boolean isFlying;

    //--回调函数-------------------------------------
    private OnChangeListener mListener;
    public void setOnChangeListener(OnChangeListener listener) {
        if (listener != null) {
            mListener = listener;
        }
    }
    public interface OnChangeListener{
        void move2dest(int curID);
    }

    public HorizontalScrollView(Context context) {
        this(context, null);
    }

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

    public HorizontalScrollView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mScroller = new HorizontalScroller();
        isFlying = false;
        initGesture(context);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // 模向移动,
        for (int i = 0; i < getChildCount(); i++) {
            View view = getChildAt(i);
            //给水平方向的每个view定位
            view.layout(i * getWidth(), 0, getWidth() + i * getWidth(), getHeight());
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        for (int i = 0; i < getChildCount(); i++) {
            View view = getChildAt(i);
            view.measure(widthMeasureSpec, heightMeasureSpec);
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mGestureDetector.onTouchEvent(event);
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            if (!isFlying) {
                move2dest();
            }
            isFlying = false;
            break;
        case MotionEvent.ACTION_MOVE:
            break;
        case MotionEvent.ACTION_UP:
            break;
        default:
            break;
        }
        return true;
    }

    public void move2dest() {
        //
        int destID = (getScrollX() + getWidth() / 2) / getWidth();
        move2dest(destID);
    }

    public void move2dest(int destID) {
        curID = destID;

        if (destID > getChildCount() - 1) {
            destID = getChildCount() - 1;
        }

        if (mListener != null) {
            mListener.move2dest(curID);
        }

        int distance = (int) (destID * getWidth() - getScrollX());
        // scrollBy(distance, 0);
        mScroller.startScroll(getScrollX(), getScrollY(), distance, 0);
        invalidate();
    }

    /** * invalidate()此方法会触发下面的方法 */
    @Override
    public void computeScroll() {
        // 如果存在偏移,就不断刷新
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), 0);
            invalidate();
        }
        super.computeScroll();
    }

    private void initGesture(Context context) {
        mGestureDetector = new GestureDetector(context, new OnGestureListener() {

            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                return false;
            }

            @Override
            public void onShowPress(MotionEvent e) {

            }

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                scrollBy((int) distanceX, 0);
                return false;
            }

            @Override
            public void onLongPress(MotionEvent e) {
            }

            @Override
            /** * 快速滑动时 */
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                isFlying = true;
                if (curID > 0 && velocityX > 0) {// 表示向左移
                    move2dest(curID - 1);
                } else if (curID < getChildCount() && velocityX < 0) {
                    move2dest(curID + 1);// 向右
                } else {
                    move2dest();// 移到原位
                }
                return false;
            }

            @Override
            public boolean onDown(MotionEvent e) {
                return false;
            }
        });
    }
}
/** * 位移计算工具类 * * @author chenlin * */
public class HorizontalScroller {

    private int startX;
    private int startY;
    private int distanceX;
    private int distanceY;

    private int currentX;
    private int currentY;

    private long startTime;
    private long duration = 1000L;

    private boolean isFinish;

    /** * * @param scrollX * x坐标 * @param scrollY * y坐标 * @param distanceX * X方向移动的距离 * @param distanceY * y方向移动的距离 */
    public void startScroll(int scrollX, int scrollY, int distanceX, int distanceY) {
        startX = scrollX;
        startY = scrollY;
        this.distanceX = distanceX;
        this.distanceY = distanceY;
        isFinish = false;
        startTime = SystemClock.uptimeMillis();
    }

    /** * 计算偏移量, * * @return true 还在移动 false:移动已经停止 */
    public boolean computeScrollOffset() {
        if (isFinish) {
            return false;
        }

        long timePassed = SystemClock.uptimeMillis() - startTime;

        if (timePassed < duration) {

            currentX = (int) (startX + distanceX * timePassed / duration);
            currentY = (int) (startY + distanceY * timePassed / duration);

            System.out.println("currentX:::" + currentX);
        } else if (timePassed >= duration) {
            currentX = startX + distanceX;
            currentY = startY + distanceY;
            isFinish = true;
        }

        return true;
    }

    public int getCurrX() {
        return currentX;
    }

    public void setCurrentX(int currentX) {
        this.currentX = currentX;
    }

    public int getCurrentY() {
        return currentY;
    }

    public void setCurrentY(int currentY) {
        this.currentY = currentY;
    }

}

使用方法

public class ScrollActivity extends Activity implements OnCheckedChangeListener, OnChangeListener {

    private int[] ids = { R.drawable.a1, R.drawable.a2, R.drawable.a3, R.drawable.a4, R.drawable.a5, R.drawable.a6 };
    private HorizontalScrollView mView;
    private LinearLayout mLayout;
    private RadioGroup mGroup;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_myscrollview);
        init();

    }

    private void init() {
        mLayout = (LinearLayout) findViewById(R.id.body_layout);
        mGroup = (RadioGroup) findViewById(R.id.radiogroup);

        mView = new HorizontalScrollView(this);

        for (int i = 0; i < ids.length; i++) {
            ImageView imageView = new ImageView(this);
            imageView.setBackgroundResource(ids[i]);
            mView.addView(imageView);
        }

        mLayout.addView(mView);

        // 随便添加一个view
        View view = getLayoutInflater().inflate(R.layout.activity_progressview, null);
        mView.addView(view, 3);

        for (int i = 0; i < mView.getChildCount(); i++) {
            RadioButton radioButton = new RadioButton(this);
            // 设置id的编号
            radioButton.setId(i);
            mGroup.setOrientation(LinearLayout.HORIZONTAL);
            mGroup.addView(radioButton);
            if (i == 0) {
                radioButton.setChecked(true);
            }
        }

        mGroup.setOnCheckedChangeListener(this);
        mView.setOnChangeListener(this);
    }

    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
        mView.move2dest(checkedId);

    }

    @Override
    public void move2dest(int curID) {
        RadioButton radioButton = (RadioButton) mGroup.getChildAt(curID);
        radioButton.setChecked(true);
    }

}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" >

    <RadioGroup  android:id="@+id/radiogroup" android:layout_width="wrap_content" android:layout_height="wrap_content" >
    </RadioGroup>

    <LinearLayout  android:id="@+id/body_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" >
    </LinearLayout>

</LinearLayout>

你可能感兴趣的:(android,水平滚动)