Android 自定义可以滚动的ViewGroup

来源:互联网 发布:html5 幸运大转盘源码 编辑:程序博客网 时间:2024/06/05 16:39

自定义一个ViewGroup,能够实现ScrollerView的部分功能,并且能够实现黏性效果,小于一定距离恢复到原来位置,大于一定距离滑动到下一个View。

public class MyScrollView extends ViewGroup {private int mScreenHeight;private int mLastY;private int mStart;private int mEnd;private Scroller mScroller;public MyScrollView (Context context) {super(context);initView(context);}public MyScrollView (Context context, AttributeSet attrs) {super(context, attrs);initView(context);}public MyScrollView (Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initView(context);}private void initView(Context context) {WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);DisplayMetrics dm = new DisplayMetrics();wm.getDefaultDisplay().getMetrics(dm);                // 获取当前屏幕高度               mScreenHeight = dm.heightPixels;mScroller = new Scroller(context);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int count = getChildCount();for (int i = 0; i < count; i++) {View child = getChildAt(i);measureChild(child, widthMeasureSpec, heightMeasureSpec);}}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {int childCound = getChildCount();// 设置ViewGroup高度MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();mlp.height = mScreenHeight * childCound;setLayoutParams(mlp);// 遍历子控件设定位置for (int i = 0; i < childCound; i++) {View child = getChildAt(i);if (child.getVisibility() != View.GONE) {child.layout(left, i * mScreenHeight, right, (i + 1) * mScreenHeight);}}}@Overridepublic boolean onTouchEvent(MotionEvent event) {int y = (int) event.getY();switch (event.getAction()) {case MotionEvent.ACTION_DOWN:mLastY = y;mStart = getScrollY();break;case MotionEvent.ACTION_MOVE:if (!mScroller.isFinished()) {                                // 停止动画                               mScroller.abortAnimation();}int dy = mLastY - y;// y偏移小于0 滑动已经到上部顶端if (getScrollY() < 0) {dy = 0;}// 滑动已经到下部顶端if (getScrollY() > getHeight() - mScreenHeight) {dy = 0;}// 滑动相对位移scrollBy(0, dy);mLastY = y;break;case MotionEvent.ACTION_UP:mEnd = getScrollY();int dScrollY = mEnd - mStart;if (dScrollY > 0) {if (dScrollY < mScreenHeight / 3) { mScroller.startScroll(0, getScrollY(), 0, -dScrollY);} else {mScroller.startScroll(0, getScrollY(), 0, mScreenHeight- dScrollY);}} else {if (-dScrollY < mScreenHeight / 3) { mScroller.startScroll(0, getScrollY(), 0, -dScrollY);} else {mScroller.startScroll(0, getScrollY(), 0, -mScreenHeight- dScrollY);}}break;}postInvalidate();return true;}// 调用startScroll()是不会有滚动效果的,只有在computeScroll()获取滚动情况,做出滚动的响应// computeScroll在父控件执行drawChild时,会调用这个方法@Overridepublic void computeScroll() {super.computeScroll();                // 想知道新位置时调用,返回true,表示动画没有结束,位置改变以提供一个新的位置               if (mScroller.computeScrollOffset()) {                        // mScroller.getCurrY()当前滚动y方向偏移                       scrollTo(0, mScroller.getCurrY());postInvalidate();}}}


0 0
原创粉丝点击