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 = 50; //水平間隔 private final int VerInterval = 20; //垂直間隔 private int viewWidth; //控制元件的寬度 private int viewHeight; //控制元件的高度 private ArrayList<String> mTexts = new ArrayList<>(); private Context mContext; private int textModePadding = 30; private int textModePaddingLeft = 50; private int textModePaddingTop = 25; private int textModePaddingRight = 50; private int textModePaddingBottom = 25; //正常樣式 private float itemTextSize = 12; 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); } } /** * 獲取控制元件的自適應高度 * * @return */ 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 + getNextHorLastPos(i) > viewWidth) { //------------修正沒有計算所在行第一個所需寬度(2017/7/10)------------ viewwidth = (measuredWidth + HorInterval * 2); viewheight += (measureHeight + VerInterval); } else { viewwidth += (measuredWidth + HorInterval); } } return viewheight; } /** * 當前按鈕所需的寬度 * @param i * @return */ 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(textModePaddingLeft, textModePaddingTop, textModePaddingRight, textModePaddingBottom); } } //清除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="15dp" />
</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="@color/colorAccent" />
<corners android:radius="15dp" />
</shape>
</item>
</layer-list>
四、例子:
final ArrayList<String> viewtexts = new ArrayList<>();
viewtexts.add("基礎資訊");
viewtexts.add("通訊資訊");
viewtexts.add("後備電源");
headViewHolde.viewGroup.addItemViews(viewtexts, GoodsViewGroup.TEV_MODE);
headViewHolde.viewGroup.chooseItemStyle(0);
headViewHolde.viewGroup.setGroupClickListener(new GoodsViewGroup.OnGroupItemClickListener() {
@Override
public void onGroupItemClick(int item) {
Toast.makeText(mContext, viewtexts.get(item), Toast.LENGTH_SHORT).show();
}
});
xml頁面
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:layout_marginTop="10dp"
android:orientation="vertical">
<com.distributionsysten.view.GoodsViewGroup
android:id="@+id/viewGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="10dp">
</com.distributionsysten.view.GoodsViewGroup>
</LinearLayout>
相關推薦
Android 自定義標籤選擇按鈕組(一)
效果圖: 一、原理: 1.其實這裡我們用到的是一個ViewGroup控制元件組,把這些按鈕加進去就有這種效果了!不過這裡要繼承ViewGroup(命名為:GoodsViewGroup)重寫裡面的一些方法。 2.主要的方法有: GoodsViewGroup按鈕組
Android 自定義標籤選擇按鈕組(二)
GoodsViewGroup修改與完善有以下幾點: 一、這裡就只支援TextView模式,以為在Button模式下,padding設定比其預設的更小時是看不到作用的,所以做了修整 二、新增GoodsViewGroupItem裡面有key跟value兩個欄位,使用者在這裡可
Android-自定義影象資源的使用(1)
Android-自定義影象資源的使用2014年4月28日 週一 天氣晴朗 心情平靜有興趣的朋友可以加本人建立的群,裡面有豐富的學習資源哦:299402133(移動開發狂熱者群)Android中有以下幾種
Android自定義控制元件開發系列(三)——仿支付寶六位支付密碼輸入頁面
在移動互聯領域,有那麼幾家龍頭一直是我等學習和追求的目標,比如支付寶、微信、餓了麼、酷狗音樂等等,大神舉不勝舉,他們設計的介面、互動方式已經培養了中國(有可能會是世界)民眾的操作習慣:舉個小例子,對話方塊“確定”按鈕的左右位置就很有學問,如果大家都是左邊取消
html自定義單選按鈕radio(CSS)
最近需要自定義radio,參考了一些別人的文章,在這裡記錄一下自己做的一個小選擇頁面。 效果圖如下:(點選按鈕前) 點選按鈕並選擇後: 顏色大小等都可以根據專案進行修改,這裡為了介面的好看,對span整個Div左浮動,選擇項右浮動。為了分割開選項,採取了給按鈕
android自定義View,實現折線圖(二)
效果圖: LineChartView類: public class LineChartView extends View { private int width; private int height; private float maxVal
Docker之自定義映象製作與執行(一)
前幾篇我們介紹了Windows下安裝Docker與第三方Nginx映象執行,這一篇我們學習怎麼自己製作映象並放在docker容器中執行起來。製作映象 製作映象首先要知道你這個專案所要依賴什麼環境下才能執行,我們的專案都是JAVA WEB專案,所以就要依賴to
怎樣為std::map的自定義key提供比較操作(一)
stl的關聯容器(map,set)的key一般要求提供 < 比較操作。假設我們有一個結構SomeKey: struct SomeKey { int a, b; }; 要想以SomeKey作為std::map的key,需要為這個結構提
Mybatis-generator修改原始碼實現自定義方法,返回List物件(一)
Mybatis-generator修改原始碼實現自定義方法,返回Lsit物件——第一篇 本文結合網上的諸多教程,詳細介紹通過修改Mybatis-generator的原始碼, 在自動生成dao層和XML檔案時,新增一個返回List的方法,資料庫使用Mysql
android--------自定義視頻控件(視頻全屏豎屏自動切換)
github get src color href 橫豎屏切換 圖片 div 分享 android播放視頻也是常用的技術,今天分享一個自定義視頻控件,支持自定義控制 UI,全屏播放, 可以實現自動橫豎屏切換的控件,跟隨手機的位置而,重力感應自動切換橫豎屏. 效果圖:
按鈕配置之自定義按鈕使用(一)——JEPLUS軟件快速開發平臺
事件 proc oss In 需求 信息 ces otto 圖片 JEPLUS按鈕配置之自定義按鈕使用(一)系統開發過程中無論是表單的默認按鈕或是列表的默認按鈕以及Action的默認按鈕有時候並不能滿足我們的業務需求,這個時
CSS自定義select選擇框樣式(右側下拉箭頭)
如圖:自定義select的箭頭樣式 HTML以及CSS程式碼如下: <select class="form_select"> <option value="0">請選擇</option> <option value=
【舉例】Android自定義Dialog——選擇一個RadioButton
1. 自定義Dialog的介面 <--!dialog_selectserver.xml--> <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://sch
Android自定義標籤列表控制元件LabelsView
無論是在移動端的App,還是在前端的網頁,我們經常會看到下面這種標籤的列表效果: 標籤從左到右擺放,一行顯示不下時自動換行。這樣的效果用Android源生的控制元件很不好實現,所以往往需要我們自己去自定義控制元件。我在開發中就遇到過幾次要實現這樣的標籤列表效果,所以就自己寫了個控制元件,放到我的
Android 自定義數字選擇器,可以根據自己的需求更改
實現效果如下: 還是以往的套路,先把那些專案所需要的給展示出來。 values下的資料夾,attrs.xml <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styl
Android 自定義帶刪除按鈕的EditText
首先建立一個類 設定成EditTextWithDel,繼承EditText。 實現程式碼如下。 @SuppressLint("AppCompatCustomView") public class EditTextWithDel extends EditText { priv
Android自定義主題樣式詳解(結合自定義title欄講解)
此篇部落格將總結主題樣式的自定義並且結合例項自定義title欄進行講解。為了方便閱讀,在此先寫明文章結構: 1.對android主題樣式的理解 (簡略結合系統自帶樣式的講解) 2.如何自定義主題樣式 (主要,有例子) 3.如何自定義titl
在Android應用中使用自定義證書的HTTPS連線(下)
因為這部分才是本文的重點,要說得詳細一點,所以單獨做成一篇來說。安全地使用自定義證書的HTTPS連線方式終極解決方案是:把證書編譯到應用中去,由應用自己來驗證證書。生成KeyStore要驗證自定義證書,首先要把證書編譯到應用中去,這需要JSSE提供的keytool工具來生成K
自定義時間選擇控制元件(仿ios滾動效果)
1.先上自定義的控制元件: /** * 滾輪選擇器 * author LH * data 2016/8/20 17:26 */ public class WheelView extends View { public static final String
Android自定義時間選擇器或者WheelView
public class PickView extends View{ public static final String TAG = "PickerView"; /** * text之間間距和minTextSize之比 */ publ