Android 自定義標籤選擇按鈕組(二)
GoodsViewGroup修改與完善有以下幾點:
一、這裡就只支援TextView模式,以為在Button模式下,padding設定比其預設的更小時是看不到作用的,所以做了修整
二、新增GoodsViewGroupItem裡面有key跟value兩個欄位,使用者在這裡可以自行修改,新增GoodsViewGroupItem比較方便管理跟資料的整理
三、在res——>values目錄下新增attrs.xml屬性給GoodsViewGroup自定義一些屬性值,這樣我們在佈局檔案中就可以來設定其(isSelector,normal_drawable,selected_drawable等等)
四、不然其修改按鈕組裡面的按鈕高度,而現在是改用設定padding比較好點,設定固定高度可能你字型設定大了就會出現一些變形
五、該按鈕新增支援有邊框的設定,如果你想做的效果跟我的一模一樣的話,你可以直接在colors.xml去修改其樣色就ok了,效果資源中的drawable就是直接引用colors.xml中的顏色,或許你想去掉邊框等等,你也可以設定GoodsViewGroup的屬性(normal_drawable,selected_drawable)
下面還是一樣先給效果圖:
1、這裡先展示主角,也是上圖中的按鈕組控制元件:GoodsViewGroup.class
/**
* Created by SoBan on 2016/8/22.
* 這裡是類似淘寶中商品尺寸按鈕組
*/
public class GoodsViewGroup extends ViewGroup {
private List<GoodsViewGroupItem> mItems = new ArrayList<>();
private Context mContext;
private int horInterval; //水平間隔
private int verInterval; //垂直間隔
private int viewWidth; //控制元件的寬度
private int viewHeight; //控制元件的高度
//按鈕水平跟垂直內邊距
private int horPadding;
private int verPadding;
//正常樣式
private float textSize;
private int bgResoureNor;
private int textColorNor;
//選中的樣式
private int bgResoureSel;
private int textColorSel;
private boolean isSelector; //是否做選擇之後的效果
public GoodsViewGroup(Context context) {
this(context, null);
}
public GoodsViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
getResources().getColor(R.color.goods_item_text_normal);
init(context, attrs);
}
private void init(Context context, AttributeSet set) {
mContext = context;
TypedArray attrs = mContext.obtainStyledAttributes(set, R.styleable.GoodsViewGroup);
isSelector = attrs.getBoolean(R.styleable.GoodsViewGroup_isSelector, true);
textSize = attrs.getDimensionPixelSize(R.styleable.GoodsViewGroup_itemTextSize, 0);
if (textSize == 0) {
textSize = getResources().getDimensionPixelSize(R.dimen.goods_item_text);//14sp
}
horInterval = attrs.getDimensionPixelSize(R.styleable.GoodsViewGroup_horInterval, 20);
verInterval = attrs.getDimensionPixelSize(R.styleable.GoodsViewGroup_verInterval, 20);
horPadding = attrs.getDimensionPixelSize(R.styleable.GoodsViewGroup_horPadding, 20);
verPadding = attrs.getDimensionPixelSize(R.styleable.GoodsViewGroup_verPadding, 10);
bgResoureNor = attrs.getResourceId(R.styleable.GoodsViewGroup_normal_drawable, R.drawable.goods_item_btn_normal);
bgResoureSel = attrs.getResourceId(R.styleable.GoodsViewGroup_selected_drawable, R.drawable.goods_item_btn_selected);
textColorNor = attrs.getColor(R.styleable.GoodsViewGroup_normal_textColor, getColorResoure(R.color.goods_item_text_normal));
textColorSel = attrs.getColor(R.styleable.GoodsViewGroup_selected_textColor, getColorResoure(R.color.goods_item_text_selected));
attrs.recycle();
}
private int getColorResoure(int resId) {
return getResources().getColor(resId);
}
/**
* 計算控制元件的大小
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
viewWidth = measureWidth(widthMeasureSpec);
viewHeight = measureHeight(heightMeasureSpec);
// 計算自定義的ViewGroup中所有子控制元件的大小
measureChildren(widthMeasureSpec, heightMeasureSpec);
// 設定自定義的控制元件ViewGroup的大小
setMeasuredDimension(viewWidth, getViewHeight());
}
private int measureWidth(int pWidthMeasureSpec) {
int result = 0;
int widthMode = MeasureSpec.getMode(pWidthMeasureSpec);
int widthSize = MeasureSpec.getSize(pWidthMeasureSpec);
switch (widthMode) {
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;
}
/**
* 計算控制元件的自適應高度
*/
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();
//------------當前按鈕按鈕是否在水平上夠位置(2017/7/10)------------
if (viewwidth + getChildCurrentWidth(i) > viewWidth) {
viewwidth = (measuredWidth + horInterval * 2);
viewheight += (measureHeight + verInterval);
} else {
viewwidth += (measuredWidth + horInterval);
}
}
return viewheight;
}
/**
* 覆寫onLayout,其目的是為了指定檢視的顯示位置,方法執行的前後順序是在onMeasure之後,因為檢視肯定是隻有知道大小的情況下,
* 才能確定怎麼擺放
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// 遍歷所有子檢視
int posLeft = 0;
int posTop = verInterval;
int posRight = horInterval;
int posBottom;
for (int i = 0; i < getChildCount(); i++) {
View childView = getChildAt(i);
// 獲取在onMeasure中計算的檢視尺寸
int measureHeight = childView.getMeasuredHeight();
int measuredWidth = childView.getMeasuredWidth();
if (posRight + getChildCurrentWidth(i) > viewWidth) {
posLeft = 0;
posTop += (measureHeight + verInterval);
}
posRight = posLeft + measuredWidth;
posBottom = posTop + measureHeight;
childView.layout(posLeft, posTop, posRight, posBottom);
posLeft += (measuredWidth + horInterval);
}
}
/**
* 獲得當前按鈕所需的寬度
*
* @param i
* @return
*/
private int getChildCurrentWidth(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 TextView childView = (TextView) getChildAt(i);
final int itemPos = i;
childView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
String valueName = ((TextView) view).getText().toString(); //白色
onGroupItemClickListener.onGroupItemClick(itemPos, getItemKey(valueName), valueName);
if (isSelector) {
chooseItemStyle(itemPos);
}
}
});
}
}
/**
* 獲取按鈕的顏色的按鈕去找1 , value->key
*
* @param itemBtnText
* @return
*/
private String getItemKey(String itemBtnText) {
for (int i = 0; i < mItems.size(); i++) {
if (mItems.get(i).getValue().equals(itemBtnText)) {
return mItems.get(i).getKey();
}
}
return "";
}
/**
* 選中那個的樣式
*
* @param pos
*/
public void chooseItemStyle(int pos) {
clearItemsStyle();
if (pos < getChildCount()) {
TextView childView = (TextView) getChildAt(pos);
childView.setBackgroundResource(bgResoureSel);
childView.setTextColor(textColorSel);
setItemPadding(childView);
}
}
/**
* 清除ViewGroup所有的樣式
*/
private void clearItemsStyle() {
for (int i = 0; i < getChildCount(); i++) {
TextView childView = (TextView) getChildAt(i);
childView.setBackgroundResource(bgResoureNor);
childView.setTextColor(textColorNor);
setItemPadding(childView);
}
}
private void setItemPadding(TextView view) {
view.setPadding(horPadding, verPadding, horPadding, verPadding);
}
public void addItemViews(List<GoodsViewGroupItem> items) {
if (items != null) {
mItems = items;
removeAllViews();
for (GoodsViewGroupItem item : items) {
addItemView(item);
}
}
}
private void addItemView(GoodsViewGroupItem item) {
TextView childView = new TextView(mContext);
childView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
childView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
childView.setBackgroundResource(bgResoureNor);
setItemPadding(childView);
childView.setTextColor(textColorNor);
childView.setText(item.getValue());
this.addView(childView);
}
public void setSelector(boolean selector) {
isSelector = selector;
}
public interface OnGroupItemClickListener {
void onGroupItemClick(int itemPos, String key, String value);
}
}
2、資料模型bean:GoodsViewGroupItem.class
/**
* @author SoBan
* @create 2017/1/7 15:25.
*/
public class GoodsViewGroupItem {
private String key;
private String value;
public GoodsViewGroupItem(String key, String value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
3、屬性資源:res—>values 中新增 attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="GoodsViewGroup">
<attr name="isSelector" format="boolean" />
<attr name="normal_drawable" format="reference" />
<attr name="selected_drawable" format="reference" />
<attr name="normal_textColor" format="color" />
<attr name="selected_textColor" format="color" />
<attr name="itemTextSize" format="dimension" />
<attr name="horInterval" format="dimension" />
<attr name="verInterval" format="dimension" />
<attr name="horPadding" format="dimension" />
<attr name="verPadding" format="dimension" />
</declare-styleable>
</resources>
4、顏色資源:res—>values 中新增 colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="goods_item_text_normal">#ff8000</color>
<color name="goods_item_text_selected">#ffffff</color>
<color name="goods_item_btn_bg_normal">#ffffff</color>
<color name="goods_item_btn_bg_selected">#ff8000</color>
<color name="goods_item_btn_bg_border">@color/goods_item_btn_bg_selected</color>
</resources>
5、按鈕正常drawable:goods_item_btn_normal.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/goods_item_btn_bg_normal" />
<stroke
android:width="1dip"
android:color="@color/goods_item_btn_bg_border" />
<corners android:radius="8dip" />
</shape>
6、按鈕選中drawable:goods_item_btn_selected.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/goods_item_btn_bg_border" />
<stroke
android:width="1dip"
android:color="@color/goods_item_btn_bg_border" />
<corners android:radius="8dip" />
</shape>
7、例子:MainActivity.class
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getName();
private GoodsViewGroup mGoodsViewGroup;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGoodsViewGroup = (GoodsViewGroup) findViewById(R.id.goods_viewgroup);
mGoodsViewGroup.addItemViews(getItems());
mGoodsViewGroup.setGroupClickListener(new GoodsViewGroup.OnGroupItemClickListener() {
@Override
public void onGroupItemClick(int itemPos, String key, String value) {
// Toast.makeText(MainActivity.this, value, Toast.LENGTH_SHORT).show();
Log.e(TAG, value);
}
});
}
private List<GoodsViewGroupItem> getItems() {
List<GoodsViewGroupItem> items = new ArrayList<>();
for (int i = 0; i < 10; i++) { items.add(new GoodsViewGroupItem(i + "", "L" + i));
}
return items;
}
}
8、例子佈局:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:hk="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<saobin.goodsviewgroup.GoodsViewGroup
android:id="@+id/goods_viewgroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
hk:horPadding="20dip"
hk:verPadding="5dip" />
</LinearLayout>