1. 程式人生 > >Android 自定義標籤選擇按鈕組(二)

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>