Android自定义ViewGroup实现受边界限制的滚动操作(3)
程序员文章站
2024-02-24 13:57:40
上一篇文章《自定义viewgroup(2)》地址:
代码
package com.example.libingyuan.horizontallistview.s...
上一篇文章《自定义viewgroup(2)》地址:
代码
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.view; 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; /** * 使用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; } /** * 滚动时需要重写的方法,用于控制滚动 */ @override public void computescroll() { //判断滚动时候停止 if (mscroller.computescrolloffset()) { //滚动到指定的位置 scrollto(mscroller.getcurrx(), mscroller.getcurry()); //这句话必须写,否则不能实时刷新 postinvalidate(); } } /** * 手指触屏事件监听 * @param event * @return */ @override public boolean ontouchevent(motionevent event) { // todo auto-generated method stub int action = event.getaction(); float x = event.getx(); switch (action) { case motionevent.action_down: if (!mscroller.isfinished()) { mscroller.abortanimation(); } mlastmotionx = event.getx(); break; case motionevent.action_move: float delt = mlastmotionx - x; mlastmotionx = x; scrollby((int) delt, 0); break; case motionevent.action_up: view lastchild=getchildat(getchildcount()-1); int finalychild= (int) (lastchild.getx()+lastchild.getwidth()-screenwidth); if (getscrollx()<0){ scrollto(0,0); } if (getscrollx()>=finalychild) scrollto(finalychild,0); invalidate(); break; default: break; } 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); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。