Android自定义viewgroup快速滑动(4)
程序员文章站
2024-02-26 18:41:16
上一篇文章自定义viewgroup(3)地址:
代码:
package com.example.libingyuan.horizontallistview....
上一篇文章自定义viewgroup(3)地址:
代码:
package com.example.libingyuan.horizontallistview.scrollviewgroup; import android.content.context; import android.util.attributeset; import android.util.displaymetrics; import android.view.motionevent; import android.view.velocitytracker; import android.view.view; import android.view.viewconfiguration; import android.view.viewgroup; import android.view.windowmanager; import android.widget.scroller; /** * 自定义viewgroup * 增加了加速度滑动 */ public class scrollviewgroup extends viewgroup { //滚动计算辅助类 private scroller mscroller; //手指落点的x坐标 private float mlastmotionx = 0; //屏幕宽度 private int screenwidth; //手指加速度辅助类 private velocitytracker mvelocitytracker; //每秒移动的最小dp private int mminimumvelocity; //每秒移动的最大dp private int mmaximumvelocity; /** * 使用new关键字创建对象的时候调用 * * @param context 上下文 */ public scrollviewgroup(context context) { this(context, null); } /** * 在xml文件中使用的时候调用 * * @param context 上下文 * @param attrs 属性:如 android:layout_width="wrap_content" */ public scrollviewgroup(context context, attributeset attrs) { this(context, attrs, 0); } /** * 在xml文件中调用,并且使用了自定义属性的时候调用 * * @param context 上下文 * @param attrs 属性:如 android:layout_width="wrap_content" * @param defstyleattr 自定义属性的id */ public scrollviewgroup(context context, attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); init(context); } /** * 初始化方法 * 初始化滚动辅助类scroller以及计算出屏幕宽度 * * @param context 上下文 */ 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; //获取最小和最大的移动距离 final viewconfiguration configuration = viewconfiguration.get(context); mminimumvelocity = configuration.getscaledminimumflingvelocity(); mmaximumvelocity = configuration.getscaledmaximumflingvelocity(); } /** * 滚动时需要重写的方法,用于控制滚动 */ @override public void computescroll() { //判断滚动时候停止 if (mscroller.computescrolloffset()) { //滚动到指定的位置 scrollto(mscroller.getcurrx(), mscroller.getcurry()); //这句话必须写,否则不能实时刷新 postinvalidate(); } } /** * 手指触屏事件监听 */ @override public boolean ontouchevent(motionevent event) { // todo auto-generated method stub int action = event.getaction(); //获取现在手指所在的位置的x坐标 float x = event.getx(); //判断触发的时间 switch (action) { //按下事件 case motionevent.action_down: //初始化或服用加速度测试器 initorresetvelocitytracker(); //测试器添加按下事件 mvelocitytracker.addmovement(event); //如果停止滚动则取消动画(即手指按下就停止滚动) if (!mscroller.isfinished()) { mscroller.abortanimation(); } //获取现在的x坐标 mlastmotionx = event.getx(); break; //移动事件 case motionevent.action_move: //测试器添加移动事件 if (mvelocitytracker != null) { mvelocitytracker.addmovement(event); } //计算移动的偏移量 float delt = mlastmotionx - x; //重置手指位置 mlastmotionx = x; //滚动 scrollby((int) delt, 0); break; //手指抬起事件 case motionevent.action_up: //测试器添加抬起事件 mvelocitytracker.addmovement(event); //添加加速度的测试时间,这里是测量1000毫秒内的加速度 mvelocitytracker.computecurrentvelocity(1000, mmaximumvelocity); //获取x方向加速度 float pxsec = mvelocitytracker.getxvelocity(); //得到最后一个子view view lastchild = getchildat(getchildcount() - 1); //获取滑动的最大滑动距离(最后一个child的右边框的坐标减去屏幕的宽度) int finalychild = (int) (lastchild.getx() + lastchild.getwidth() - screenwidth); //如果x的加速度大于系统设定的最小移动距离,就可以惯性滑动 if (math.abs(pxsec) > mminimumvelocity) mscroller.fling(getscrollx(), 0, (int) -pxsec, 0, 0, finalychild, 0, 0); //如果滑动的距离小于第一个控件的最左边(0)则回弹至(0,0)点 if (getscrollx() < 0) { scrollto(0, 0); } //如果滑动的距离大于最大可滑动距离则滑动到最后一个子view if (getscrollx() >= finalychild) scrollto(finalychild, 0); //刷新界面 invalidate(); //清空测试器 recyclevelocitytracker(); break; default: break; } return true; } /** * 创建或复用加速度测试器 */ private void initorresetvelocitytracker() { if (mvelocitytracker == null) { mvelocitytracker = velocitytracker.obtain(); } else { mvelocitytracker.clear(); } } /** * 回收加速度测试器,防止内存泄漏 */ private void recyclevelocitytracker() { if (mvelocitytracker != null) { mvelocitytracker.recycle(); mvelocitytracker = null; } } @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); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
Android自定义viewgroup快速滑动(4)
-
Android自定义ViewGroup实现受边界限制的滚动操作(3)
-
Android自定义viewgroup可滚动布局 GestureDetector手势监听(5)
-
自定义滑动按钮为例图文剖析Android自定义View绘制
-
Android自定义FloatingActionButton滑动行为只隐藏不出现的问题小结
-
Android自定义ViewGroup实现受边界限制的滚动操作(3)
-
Android自定义ViewGroup横向布局(1)
-
Android自定义ViewGroup实现可滚动的横向布局(2)
-
Android自定义viewgroup快速滑动(4)
-
Android自定义viewgroup 使用adapter适配数据(6)