Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android實現淘寶選中商品尺寸的按鈕組實例

Android實現淘寶選中商品尺寸的按鈕組實例

編輯:關於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實現淘寶選中商品不同尺寸的按鈕組的全部內容了,如果本文有什麼問題歡迎大家指出,大家共同進步!希望本文對大家的學習和工作能有所幫助哦~

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved