今天利用GestureDetector这个手势类和Scroller滑动类写一篇图片的滑动浏览的ViewGroup。效果图如下:献上我最爱的小龙女。
onTouchEvent 可以实现View的滑动,通过触摸事件的类型,改变view的坐标
Scroller Scroller有两个方法可以实现View的滑动,scrollTo与scrollBy这两个方法,scrollTo:是从一个坐标移动到另一个坐标,scrollBy:是移动的滑动的距离。
GestureDetector 手势滑动的这个类也可以实现View的移动,在GestureDetector.OnGestureListener()中可以拦截down事件,onShowPRess事件,onscroll事件等
还有其他的实现方式就不多说了,直接进入今天要实现的滑动。 首先要实现的是自定义的ViewGroup,首先重写构造类,和onLayout及onMeasure方法。
@Overrideprotected void onLayout(boolean b, int i, int i1, int i2, int i3) { for (int j = 0; j < getChildCount(); j++) { View view = getChildAt(j); view.layout(getWidth() * j, 0, getWidth() * j + getWidth(), getHeight()); }}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); if (widthMode == MeasureSpec.EXACTLY) { width = widthSize; } else { throw new IllegalArgumentException("请固定宽和高"); } if (heightMode == MeasureSpec.EXACTLY) { height = heightSize; } else { throw new IllegalArgumentException("请固定宽和高"); } setMeasuredDimension(width, height);}在onLayout方法中,后面的四个参数分别是左边坐标,顶部坐标,右边坐标和下部坐标。在layout方法中为通过addView方法加进的View分别指定位置。 接着初始化我们需要的Scroller类和手势滑动类:
private void init() { scroller = new Scroller(getContext()); addGestureDetector();} /** * 添加一个手势滑动的监听 */private void addGestureDetector() { gestureDetector = new GestureDetector(new GestureDetector.OnGestureListener() { @Override public boolean onDown(MotionEvent motionEvent) { return false; } @Override public void onShowPress(MotionEvent motionEvent) { } @Override public boolean onSingleTapUp(MotionEvent motionEvent) { return false; } /** * 拦截掉onscroll事件,并做判断,当在第一页时若继续向右滑动,则不拦截,当在最后一页时若继续向左滑动则不拦截 * @param motionEvent * @param motionEvent1 * @param v * @param v1 * @return */ @Override public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) { if (currentPage == 0 && v < 0) { return false; } if (currentPage == getChildCount() - 1 && v > 0) return false; scrollBy((int) v, 0); return true; } @Override public void onLongPress(MotionEvent motionEvent) { } @Override public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) { return false; } });}然后添加手势滑动之后需要绑定MotionEvent 就需要重写onTouchEvent的方法对MotionEvent 进行绑定
@Overridepublic boolean onTouchEvent(MotionEvent event) { gestureDetector.onTouchEvent(event); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: downx = (int) event.getX(); downy = (int) event.getY(); break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: int upx = (int) event.getX(); int upy = (int) event.getY(); if (upx - downx > getWidth() / 3) { currentPage--; } else if (upx - downx < -getWidth() / 3) { currentPage++; } uodate(currentPage); break; } return true;}首先绑定MotionEvent 计算down事件的坐标与up事件的坐标然后通过滑动的距离设置是否滑动到下一页 ,然后再update方法里面通过Scroller进行滑动。
/** * 更新滑动的距离 * 通过滑动页数控制显示的图片 * * @param index */private void uodate(int index) { if (index <= 0) { currentPage = 0; } else if (index >= getChildCount() - 1) { currentPage = getChildCount() - 1; } dx = getWidth() * currentPage - getScrollX(); scroller.startScroll(getScrollX(), 0, dx, 0); invalidate();}/** * scroller调用startScroll时必须配合computeScroll一起使用 */@Overridepublic void computeScroll() { if (scroller.computeScrollOffset()) { scrollTo(scroller.getCurrX(), 0); invalidate(); }}首先判断了下滑动显示的位置的下标是否超过当前第一张图片的下标和滑动显示的位置的下标是否超过最后一张图片的下标的位置。然后计算出滑动的距离。调用 scroller.startScroll(getScrollX(), 0, dx, 0);第一个参数标示滑动的x坐标,第三个参数标示滑动的x轴上的距离。然后调用 invalidate();绘制。scroller调用startScroll时必须配合computeScroll一起使用。mScroller.computeScrollOffset() ;返回值为boolean,true说明滚动尚未完成,false说明滚动已经完成。 scrollTo(scroller.getCurrX(), 0);scroller.getCurrX();获取mScroller当前水平滚动的位置。然后再调用 invalidate();一直绘制。 最后在MainActivity中使用。
private void setImage() { for (int i = 0; i < images.length; i++) { ImageView imageView = new ImageView(this); imageView.setScaleType(ImageView.ScaleType.FIT_XY); imageView.setImageResource(images[i]); defineViewGroup.addView(imageView); }}新闻热点
疑难解答