Android开发之瀑布流控件的实现与使用方法示例
程序员文章站
2023-12-14 16:29:58
本文实例讲述了android开发之瀑布流控件的实现与使用方法。分享给大家供大家参考,具体如下:
public class flowlayout extends v...
本文实例讲述了android开发之瀑布流控件的实现与使用方法。分享给大家供大家参考,具体如下:
public class flowlayout extends viewgroup { /**行里子view之间的行距离*/ public int mhorizontolspace = util.getdimen(r.dimen.top_padding); /**行里子view之间的垂直距离*/ public int mverticalspace = util.getdimen(r.dimen.top_padding); /**创建行的集合*/ private list<line> mlines = new arraylist<line>(); /**当前行*/ private line mcurrentline; /**当前行使用的宽度*/ private int mcurrentusewidth = 0; /**父容器的宽高*/ private int parentwidthsize; private int parentheightsize; public flowlayout(context context, attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); } public flowlayout(context context, attributeset attrs) { super(context, attrs); } public flowlayout(context context) { super(context); } @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { //0.先清空行集合里的数据 clear(); //1.得到父viewgroup的模式与大小 int parentwidthmode = measurespec.getmode(widthmeasurespec);// parentwidthsize = measurespec.getsize(widthmeasurespec) - getpaddingleft() - getpaddingright(); int parentheightmode = measurespec.getmode(heightmeasurespec); parentheightsize = measurespec.getsize(heightmeasurespec) - getpaddingbottom() - getpaddingtop(); /* 每个子view都是包裹内容 * layout.addview(mtextview, new linearlayout.layoutparams(layoutparams.wrap_content * 得到每个孩子的测量规则 */ //2.得到每个孩子的模式 int childwidthmode = parentwidthmode == measurespec.exactly ? measurespec.exactly : parentwidthmode; int childheightmode = parentheightmode == measurespec.exactly ? measurespec.exactly : parentheightmode; //3.根据模式得到子控件的大小 int childwidthmeasurespec = measurespec.makemeasurespec(childwidthmode, parentwidthsize); int childheightmeasurespec = measurespec.makemeasurespec(childheightmode, parentheightsize); //得到子view的个数 int count = getchildcount(); //创建新的行 mcurrentline = new line(); for (int i = 0; i < count; i++) { view childview = getchildat(i); //4.测量每个孩子 childview.measure(childwidthmeasurespec, childheightmeasurespec); //5.得到测量后的孩子的宽高 int childmeasurewidth = measurespec.getsize(childwidthmeasurespec); //int childmeasureheight = measurespec.getsize(childheightmeasurespec); //6.得到此行使用的宽度 mcurrentusewidth += childmeasurewidth; //7.判断此行的宽度是否大于父控件的宽度,如果大于则换行 if (mcurrentusewidth > parentwidthsize) { //8.如果当前的子view的宽度大于父容器的宽度,强行把这个view添加的集合里 if (mcurrentline.getchildcount()<1) { mlines.add(mcurrentline); } //9.换行 newline(); }else { //8.把当前子view添加到行里 mcurrentline.addchild(childview); //9.添加间隔 mcurrentusewidth += mhorizontolspace; if (mcurrentusewidth > parentwidthsize) { //10.换行 newline(); } } } //11.如果集合里没有添加当前行,则把当前添加到集合 if (!mlines.contains(mcurrentline)) { mlines.add(mcurrentline); } //12.设置富容器的总宽高 int parentwidth = parentwidthsize + getpaddingleft() + getpaddingright(); int parentheight = (mlines.size()-1) * mverticalspace + getpaddingbottom() + getpaddingtop(); for(line line : mlines){ //得到所以line的高度 parentheight += line.getheight(); } //13.resolvesize表示哪个高度合适,就用哪个 setmeasureddimension(parentwidth, resolvesize(parentheightsize, parentheight)); /*setmeasureddimension(getdefaultsize(getsuggestedminimumwidth(), widthmeasurespec), getdefaultsize(getsuggestedminimumheight(), heightmeasurespec));*/ } /** * 换行 */ private void newline() { //a.先把当前的行添加到集合 mlines.add(mcurrentline); //b.创建新的一行 mcurrentline = new line(); //c.新行里的使用的行必须设置为0 mcurrentusewidth = 0; } public void clear() { mlines.clear(); mcurrentline = null; mcurrentusewidth = 0; } @override protected void onlayout(boolean changed, int l, int t, int r, int b) { //15.得到每个line孩子的左上角的坐标 int left = l + getpaddingleft(); int top = t + getpaddingtop(); //现在容器里只有line是子孩子 for (int i = 0; i < mlines.size(); i++) { line line = mlines.get(i); //16.把分配位置给line去处理 line.layout(left, top); //17.设置第一行后的其它行的top数值 top += line.getheight() + mverticalspace; } } /** * 行类,用来封装一行的view */ private class line{ /**当前行的宽度*/ private int mwidth = 0; /**当前行的高度*/ private int mheight = 0; /**每个孩子得到的剩余空间*/ int mchildpdding = 0; private list<view> children = new arraylist<view>(); public void addchild(view childview) { children.add(childview); //取得之view里最高的高度 if (childview.getmeasuredheight() > mheight) { mheight = childview.getmeasuredheight(); } //18.得到行宽度 mwidth += childview.getmeasuredwidth(); } /** * 定位每个line在富容器里的额位置 * @param left * @param top */ public void layout(int left, int top) { //18.得到行宽度 mwidth += mhorizontolspace * (children.size() -1); //19.得到剩余的宽度大小 //int padding = getmeasuredwidth() - mwidth; int padding = parentwidthsize - mwidth; if (padding > 0) { mchildpdding = padding / children.size(); } // getwidth()view显示的时候大小,如果view没显示,这个值就为0,步包括隐藏的部分, getmeasuredwidth()控件实际大小,包括隐藏的部分 //一般来说 getmeasuredwidth() > getwidth(); for (int i = 0; i < children.size(); i++) { view child = children.get(i); //第一种:有间隔的flow int bottom = child.getmeasuredheight() + top; //20.把剩余的空间分配给每个view int right = child.getmeasuredwidth() + left + mchildpdding; //第二种:无间隔的flow // int bottom = getmeasuredheight() + top; // int right = getmeasuredwidth() + left; //第一个child的位置 child.layout(left, top, right, bottom); //第二个及后面child的right right += child.getmeasuredwidth() + mhorizontolspace + mchildpdding; } } /** * 得到子view的大小 * @return */ public int getchildcount() { if (children != null) { return children.size(); } return 0; } public int getheight() { return mheight; } } }
使用方法:
public class topfragment extends fragment{ @override public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { scrollview scrollview = new scrollview(getactivity()); flowlayout layout = new flowlayout(getactivity()); layout.setbackgrounddrawable(util.getdrawable(r.drawable.list_item_bg)); int padding = util.getdimen(r.dimen.top_padding); layout.setpadding(padding, padding, padding, padding); gradientdrawable pressdrawable = drawableutil.createdrawable(0xffcecece); for (int i = 0; i < mdatas.size(); i++) { mtextview = new textview(getactivity()); mtextview.settext(mdatas.get(i)); gradientdrawable randomdrawable = drawableutil.createrandomdrawable(); statelistdrawable statelistdrawable = drawableutil.createstatedrawable(pressdrawable, randomdrawable); mtextview.setbackgrounddrawable(statelistdrawable); mtextview.settextcolor(color.white); int left = util.px2dip(7); int top = util.px2dip(4); int right = util.px2dip(7); int bottom = util.px2dip(4); mtextview.setpadding(left, top, right, bottom); mtextview.settag(mdatas.get(i)); mtextview.setonclicklistener(this); layout.addview(mtextview, new linearlayout.layoutparams(layoutparams.wrap_content, - 2)); } scrollview.addview(layout); } return scrollview; }
工具类:
public class drawableutil { /** * 创建随机背景的drawable * @return */ public static gradientdrawable createrandomdrawable(){ gradientdrawable drawable = new gradientdrawable(); drawable.setcornerradius(util.px2dip(5)); random random = new random(); int red = random.nextint(200) + 20; int green = random.nextint(200) + 20; int blue = random.nextint(200) + 20; int color = color.rgb(red, green, blue); drawable.setcolor(color); return drawable; } /** * 创建带有背景的drawable * @return */ public static gradientdrawable createdrawable(int color){ gradientdrawable drawable = new gradientdrawable(); drawable.setcornerradius(util.px2dip(5)); drawable.setcolor(color); return drawable; } /** * 状态选择器 * @param press * @param normal * @return */ public static statelistdrawable createstatedrawable(drawable press, drawable normal){ statelistdrawable drawable = new statelistdrawable(); //按下 drawable.addstate(new int[]{android.r.attr.state_pressed}, press); //正常 drawable.addstate(new int[]{}, normal); return drawable; } }
更多关于android相关内容感兴趣的读者可查看本站专题:《android窗口相关操作技巧总结》、《android开发入门与进阶教程》、《android调试技巧与常见问题解决方法汇总》、《android基本组件用法总结》、《android视图view技巧总结》、《android布局layout技巧总结》及《android控件用法总结》
希望本文所述对大家android程序设计有所帮助。