欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android实现淘宝选中商品尺寸的按钮组实例

程序员文章站 2024-03-06 21:16:38
话不多说,先上个效果图: 现在我们就来说说里面的一些原理把! 一、原理: 1.其实这里我们用到的是一个viewgroup控件组,把这些按钮加进去就有这种效果了!不...

话不多说,先上个效果图:

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>这样呢?其实这里我是想做一个泛型,可以使用与buttontextview,而这里的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实现淘宝选中商品不同尺寸的按钮组的全部内容了,如果本文有什么问题欢迎大家指出,大家共同进步!希望本文对大家的学习和工作能有所帮助哦~