Android 自定义水平滚动的容器

来源:互联网 发布:地基处理计算软件 编辑:程序博客网 时间:2024/05/29 14:42
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>
0 0