Android实现淘宝选中商品尺寸的按钮组实例
话不多说,先上个效果图:
现在我们就来说说里面的一些原理把!
一、原理:
1.其实这里我们用到的是一个viewgroup
控件组,把这些按钮加进去就有这种效果了!不过这里要继承viewgroup
(命名为:goodsviewgroup
)重写里面的一些方法。
2.主要的方法有:
goodsviewgroup按钮组的控件大小
protected void onmeasure(int widthmeasurespec, int heightmeasurespec)
里面的按钮每个的位置坐标
protected void onlayout(boolean changed, int l, int t, int r, int b)
这两个方法的具体使用大家可以网上查阅资料,这里就不多说了!
二、代码:
/** * created by shaolin on 2016/8/22. * 这里是类似淘宝中商品尺寸按钮组(这里做了支持button,textview) */ public class goodsviewgroup<x extends textview> extends viewgroup { public static final string btn_mode = "btnmode"; //按钮模式 public static final string tev_mode = "tevmode"; //文本模式 private static final string tag = "iviewgroup"; private final int horinterval = 10; //水平间隔 private final int verinterval = 10; //垂直间隔 private int viewwidth; //控件的宽度 private int viewheight; //控件的高度 private arraylist<string> mtexts = new arraylist<>(); private context mcontext; private int textmodepadding = 15; //正常样式 private float itemtextsize = 18; private int itembgresnor = r.drawable.goods_item_btn_normal; private int itemtextcolornor = color.parsecolor("#000000"); //选中的样式 private int itembgrespre = r.drawable.goods_item_btn_selected; private int itemtextcolorpre = color.parsecolor("#ffffff"); public goodsviewgroup(context context) { this(context, null); } public goodsviewgroup(context context, attributeset attrs) { super(context, attrs); mcontext = context; } /** * 计算控件的大小 */ @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { super.onmeasure(widthmeasurespec, heightmeasurespec); viewwidth = measurewidth(widthmeasurespec); viewheight = measureheight(heightmeasurespec); log.e(tag, "onmeasure:" + viewwidth + ":" + viewheight); // 计算自定义的viewgroup中所有子控件的大小 measurechildren(widthmeasurespec, heightmeasurespec); // 设置自定义的控件myviewgroup的大小 setmeasureddimension(viewwidth, getviewheight()); } private int measurewidth(int pwidthmeasurespec) { int result = 0; int widthmode = measurespec.getmode(pwidthmeasurespec); int widthsize = measurespec.getsize(pwidthmeasurespec); switch (widthmode) { /** * mode共有三种情况,取值分别为measurespec.unspecified, measurespec.exactly, * measurespec.at_most。 * * * measurespec.exactly是精确尺寸, * 当我们将控件的layout_width或layout_height指定为具体数值时如andorid * :layout_width="50dip",或者为fill_parent是,都是控件大小已经确定的情况,都是精确尺寸。 * * * measurespec.at_most是最大尺寸, * 当控件的layout_width或layout_height指定为wrap_content时 * ,控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可 * 。因此,此时的mode是at_most,size给出了父控件允许的最大尺寸。 * * * measurespec.unspecified是未指定尺寸,这种情况不多,一般都是父控件是adapterview, * 通过measure方法传入的模式。 */ case measurespec.at_most: case measurespec.exactly: result = widthsize; break; } return result; } private int measureheight(int pheightmeasurespec) { int result = 0; int heightmode = measurespec.getmode(pheightmeasurespec); int heightsize = measurespec.getsize(pheightmeasurespec); switch (heightmode) { case measurespec.unspecified: result = getsuggestedminimumheight(); break; case measurespec.at_most: case measurespec.exactly: result = heightsize; break; } return result; } /** * 覆写onlayout,其目的是为了指定视图的显示位置,方法执行的前后顺序是在onmeasure之后,因为视图肯定是只有知道大小的情况下, * 才能确定怎么摆放 */ @override protected void onlayout(boolean changed, int l, int t, int r, int b) { // 遍历所有子视图 int posleft = horinterval; int postop = verinterval; int posright; int posbottom; for (int i = 0; i < getchildcount(); i++) { view childview = getchildat(i); // 获取在onmeasure中计算的视图尺寸 int measureheight = childview.getmeasuredheight(); int measuredwidth = childview.getmeasuredwidth(); if (posleft + getnexthorlastpos(i) > viewwidth) { posleft = horinterval; postop += (measureheight + verinterval); } posright = posleft + measuredwidth; posbottom = postop + measureheight; childview.layout(posleft, postop, posright, posbottom); posleft += (measuredwidth + horinterval); } } //获取控件的自适应高度 private int getviewheight() { int viewwidth = horinterval; int viewheight = verinterval; if (getchildcount() > 0) { viewheight = getchildat(0).getmeasuredheight() + verinterval; } for (int i = 0; i < getchildcount(); i++) { view childview = getchildat(i); // 获取在onmeasure中计算的视图尺寸 int measureheight = childview.getmeasuredheight(); int measuredwidth = childview.getmeasuredwidth(); if (viewwidth + getnexthorlastpos(i) > viewwidth) { viewwidth = horinterval; viewheight += (measureheight + verinterval); } else { viewwidth += (measuredwidth + horinterval); } } return viewheight; } private int getnexthorlastpos(int i) { return getchildat(i).getmeasuredwidth() + horinterval; } private ongroupitemclicklistener ongroupitemclicklistener; public void setgroupclicklistener(ongroupitemclicklistener listener) { ongroupitemclicklistener = listener; for (int i = 0; i < getchildcount(); i++) { final x childview = (x) getchildat(i); final int itempos = i; childview.setonclicklistener(new onclicklistener() { @override public void onclick(view view) { ongroupitemclicklistener.ongroupitemclick(itempos); chooseitemstyle(itempos); } }); } } //选中那个的样式 public void chooseitemstyle(int pos) { clearitemsstyle(); if (pos < getchildcount()) { x childview = (x) getchildat(pos); childview.setbackgroundresource(itembgrespre); childview.settextcolor(itemtextcolorpre); setitempadding(childview); } } private void setitempadding(x view) { if (view instanceof button) { view.setpadding(textmodepadding, 0, textmodepadding, 0); } else { view.setpadding(textmodepadding, textmodepadding, textmodepadding, textmodepadding); } } //清除group所有的样式 private void clearitemsstyle() { for (int i = 0; i < getchildcount(); i++) { x childview = (x) getchildat(i); childview.setbackgroundresource(itembgresnor); childview.settextcolor(itemtextcolornor); setitempadding(childview); } } public void additemviews(arraylist<string> texts, string mode) { mtexts = texts; removeallviews(); for (string text : texts) { additemview(text, mode); } } private void additemview(string text, string mode) { x childview = null; switch (mode) { case btn_mode: childview = (x) new button(mcontext); break; case tev_mode: childview = (x) new textview(mcontext); break; } childview.setlayoutparams(new layoutparams(layoutparams.wrap_content, layoutparams.wrap_content)); childview.settextsize(itemtextsize); childview.setbackgroundresource(itembgresnor); setitempadding(childview); childview.settextcolor(itemtextcolornor); childview.settext(text); this.addview(childview); } public string getchoosetext(int itemid) { if (itemid >= 0) { return mtexts.get(itemid); } return null; } public void setitemtextsize(float itemtextsize) { this.itemtextsize = itemtextsize; } public void setitembgresnor(int itembgresnor) { this.itembgresnor = itembgresnor; } public void setitemtextcolornor(int itemtextcolornor) { this.itemtextcolornor = itemtextcolornor; } public void setitembgrespre(int itembgrespre) { this.itembgrespre = itembgrespre; } public void setitemtextcolorpre(int itemtextcolorpre) { this.itemtextcolorpre = itemtextcolorpre; } public interface ongroupitemclicklistener { void ongroupitemclick(int item); } }
上面提供了可以设置按钮组的item的一些样式,还有这个goodsviewgroup
为什么要写成goodsviewgroup<x extends textview>
这样呢?其实这里我是想做一个泛型,可以使用与button
跟textview
,而这里的button
本生就是继承textview
所以在代码中还要进行一个判断,可以看上面方法setitempadding(x view)
。那到了这里,有些好友可能就会问,为什么要搞两个呢?
其实这里因为textview
的不会自动有设置padding
的,而button
是有自动设置padding
。这个时候你就要看看你是先要那种效果!不过通过我的代码中如果是选择textview
的话,这里也设置了一个padding
给他,不然会很难看!
两种模式的写法:
1.button :
goodsviewgroup<button> mgroup; mgroup.additemviews(viewtexts, goodsviewgroup.btn_mode);
2.textview
goodsviewgroup<textview> mgroup; mgroup.additemviews(viewtexts, goodsviewgroup.tev_mode);
三、drawable文件:上面涉及到的按钮选中与正常的两个drawable
1.goods_item_btn_normal.xml
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item> <shape> <solid android:color="#f5f5f5" /> <corners android:radius="15.0dip" /> </shape> </item> </layer-list>
2.goods_item_btn_selected.xml
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item> <shape> <solid android:color="#fe4f00" /> <corners android:radius="15.0dip" /> </shape> </item> </layer-list>
四、例子:
buttongroupactivity
/** * created by shaolin on 2016/8/22. */ public class buttongroupactivity extends activity implements goodsviewgroup.ongroupitemclicklistener, view.onclicklistener { private goodsviewgroup<textview> mgroup; private button msubmitbtn; private arraylist<string> viewtexts = new arraylist<>(); private int chooseid = -1; private string choosetext; @override protected void oncreate(bundle savedinstancestate) { setcontentview(r.layout.activity_buttongroup); mgroup = (goodsviewgroup) findviewbyid(r.id.viewgroup); msubmitbtn = (button) findviewbyid(r.id.submitbtn); string text; for (int i = 0; i < 10; i++) { text = "l" + i; viewtexts.add(text); } mgroup.additemviews(viewtexts, goodsviewgroup.tev_mode); mgroup.setgroupclicklistener(this); msubmitbtn.setonclicklistener(this); super.oncreate(savedinstancestate); } @override public void ongroupitemclick(int item) { chooseid = item; choosetext = mgroup.getchoosetext(item); } @override public void onclick(view view) { if (chooseid >= 0) { showtoast("id:" + chooseid + ";text:" + choosetext); } else { showtoast("请选择"); } } private void showtoast(string text) { toast.maketext(buttongroupactivity.this, text, toast.length_short).show(); } }
activity_buttongroup.xml
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/linear_ayout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.example.jisuanqi.goodsviewgroup android:id="@+id/viewgroup" android:layout_width="match_parent" android:layout_height="wrap_content"> </com.example.jisuanqi.goodsviewgroup> <button android:id="@+id/submitbtn" android:text="确定" android:layout_width="match_parent" android:layout_height="wrap_content" /> </linearlayout>
总结
以上就是关于android实现淘宝选中商品不同尺寸的按钮组的全部内容了,如果本文有什么问题欢迎大家指出,大家共同进步!希望本文对大家的学习和工作能有所帮助哦~
上一篇: Java中正则表达式去除html标签