Android自定义viewgroup可滚动布局 GestureDetector手势监听(5)
程序员文章站
2024-02-24 09:19:40
这篇效果和上一篇:的效果是一样的,但是不再在ontouchevent中写代码,而是使用系统自带的类gesturedetector来监听手势以及滑动事件等等,它内置了滑动,点...
这篇效果和上一篇:的效果是一样的,但是不再在ontouchevent中写代码,而是使用系统自带的类gesturedetector来监听手势以及滑动事件等等,它内置了滑动,点击,长按等事件,而且有快速滑动,比较方便,比自己写的细节处理要好。
代码:
package com.example.libingyuan.horizontallistview.scrollviewgroup; import android.content.context; import android.util.attributeset; import android.util.displaymetrics; import android.view.gesturedetector; import android.view.motionevent; import android.view.view; import android.view.viewgroup; import android.view.windowmanager; import android.widget.scroller; /** * 自定义viewgroup(横向滚动) */ public class scrollviewgroup extends viewgroup { //滚动计算辅助类 private scroller mscroller; //屏幕宽度 private int screenwidth; //可以移动的最大距离 private int mmaxdistance; //自定义手势监听类 private scrolltouchlisener mtouchlisener; //手势监听 private gesturedetector mdetector; /** * 使用new关键字创建对象的时候调用 */ public scrollviewgroup(context context) { this(context, null); } /** * 在xml文件中使用的时候调用 */ public scrollviewgroup(context context, attributeset attrs) { this(context, attrs, 0); } /** * 在xml文件中调用,并且使用了自定义属性的时候调用 */ public scrollviewgroup(context context, attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); init(context); } /** * 初始化方法 * 初始化滚动辅助类scroller以及计算出屏幕宽度 */ private void init(context context) { //初始化辅助类 mscroller = new scroller(context); //获取屏幕宽度 windowmanager manager = (windowmanager) context .getsystemservice(context.window_service); displaymetrics outmetrics = new displaymetrics(); manager.getdefaultdisplay().getmetrics(outmetrics); screenwidth = outmetrics.widthpixels; //手势指示器初始化 mtouchlisener = new scrolltouchlisener(); mdetector = new gesturedetector(context, mtouchlisener); } /** * 滚动时需要重写的方法,用于控制滚动 */ @override public void computescroll() { //判断滚动时候停止 if (mscroller.computescrolloffset()) { //滚动到指定的位置 scrollto(mscroller.getcurrx(), mscroller.getcurry()); //这句话必须写,否则不能实时刷新 postinvalidate(); } } /** * 手指触屏事件监听 */ @override public boolean ontouchevent(motionevent event) { mdetector.ontouchevent(event); if (event.getaction() == motionevent.action_up) { this.onup(event); } return true; } /* *测量方法,测量父布局的宽度和高度 */ @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { //重新设置宽高 this.setmeasureddimension(measurewidth(widthmeasurespec, heightmeasurespec), measureheight(widthmeasurespec, heightmeasurespec)); } /** * 测量宽度 */ private int measurewidth(int widthmeasurespec, int heightmeasurespec) { // 宽度 int sizewidth = measurespec.getsize(widthmeasurespec); int modewidth = measurespec.getmode(widthmeasurespec); //父控件的宽(wrap_content) int width = 0; int childcount = getchildcount(); //重新测量子view的宽度,以及最大高度 for (int i = 0; i < childcount; i++) { view child = getchildat(i); measurechild(child, widthmeasurespec, heightmeasurespec); marginlayoutparams lp = (marginlayoutparams) child.getlayoutparams(); int childwidth = child.getmeasuredwidth() + lp.leftmargin + lp.rightmargin; width += childwidth; } return modewidth == measurespec.exactly ? sizewidth : width; } /** * 测量高度 */ private int measureheight(int widthmeasurespec, int heightmeasurespec) { //高度 int sizeheight = measurespec.getsize(heightmeasurespec); int modeheight = measurespec.getmode(heightmeasurespec); //父控件的高(wrap_content) int height = 0; int childcount = getchildcount(); //重新测量子view的宽度,以及最大高度 for (int i = 0; i < childcount; i++) { view child = getchildat(i); measurechild(child, widthmeasurespec, heightmeasurespec); marginlayoutparams lp = (marginlayoutparams) child.getlayoutparams(); int childheight = child.getmeasuredheight() + lp.topmargin + lp.bottommargin; height += childheight; } height = height / childcount; return modeheight == measurespec.exactly ? sizeheight : height; } /** * 给子布局设定位置 */ @override protected void onlayout(boolean changed, int l, int t, int r, int b) { int childleft = 0;//子view左边的间距 int childwidth;//子view的宽度 int height = getheight();//屏幕的宽度 int childcount = getchildcount();//子view的数量 for (int i = 0; i < childcount; i++) { view child = getchildat(i); marginlayoutparams lp = (marginlayoutparams) child.getlayoutparams(); childwidth = child.getmeasuredwidth() + lp.leftmargin + lp.rightmargin; child.layout(childleft, 0, childleft + childwidth, height); childleft += childwidth; } } @override public layoutparams generatelayoutparams(attributeset attrs) { return new marginlayoutparams(getcontext(), attrs); } /* *按下事件 action_down */ public boolean ondown(motionevent e) { //如果停止滚动则取消动画(即手指按下就停止滚动) if (!mscroller.isfinished()) { mscroller.abortanimation(); } return false; } /* *抬起事件 action_up */ public boolean onup(motionevent e) { //得到最后一个子view view lastchild = getchildat(getchildcount() - 1); //获取滑动的最大滑动距离(最后一个child的右边框的坐标减去屏幕的宽度) int finalychild = (int) (lastchild.getx() + lastchild.getwidth() - screenwidth); mmaxdistance = finalychild; //如果滑动的距离小于第一个控件的最左边(0)则回弹至(0,0)点 if (getscrollx() < 0) { scrollto(0, 0); } //如果滑动的距离大于最大可滑动距离则滑动到最后一个子view if (getscrollx() >= finalychild) scrollto(finalychild, 0); //刷新界面 invalidate(); return false; } /* *action_down 、短按不移动 */ public void onshowpress(motionevent e) { } /* *短按action_down、action_up */ public boolean onsingletapup(motionevent e) { return false; } /* *action_down 、慢滑动 */ public boolean onscroll(motionevent e1, motionevent e2, float distancex, float distancey) { //滚动 scrollby((int) distancex, 0); return false; } // action_down 、长按不滑动 public void onlongpress(motionevent e) { } /* *action_down 、快滑动、 action_up */ public boolean onfling(motionevent e1, motionevent e2, float velocityx, float velocityy) { mscroller.fling(getscrollx(), 0, (int) -velocityx, 0, 0, mmaxdistance, 0, 0); return false; } /** * 自定义手势监听类 */ private class scrolltouchlisener implements gesturedetector.ongesturelistener { //按下事件 @override public boolean ondown(motionevent e) { return scrollviewgroup.this.ondown(e); } //单击事件 @override public void onshowpress(motionevent e) { scrollviewgroup.this.onshowpress(e); } //手指抬起事件 @override public boolean onsingletapup(motionevent e) { return scrollviewgroup.this.onsingletapup(e); } //滚动事件 @override public boolean onscroll(motionevent e1, motionevent e2, float distancex, float distancey) { return scrollviewgroup.this.onscroll(e1, e2, distancex, distancey); } //长按事件 @override public void onlongpress(motionevent e) { scrollviewgroup.this.onlongpress(e); } //滑动事件 @override public boolean onfling(motionevent e1, motionevent e2, float velocityx, float velocityy) { return scrollviewgroup.this.onfling(e1, e2, velocityx, velocityy); } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。