因為drop-down的功能基本上提供於 Android 3.0以上的平台
因此Spinner也必須是在3.0以上的平台才能直接使用
這篇之所以會產生是因為當初開發的平台不到 3.0
又需要下拉式選單的功能, 也不考慮使用一些知名library如 ActionBarSherlock
因此只好自行觀察原理, 然後刻一個
依照本篇的作法, 可以做出像是Android Spinner的元件跟擴充型Spinner
製作spinner首先需要三個檔案
Spinner.java //Spinner object 本身 spinner_title_layout.xml spinner_item_layout.xml
Spinner.java 本身控制 Spinner 的主體
也就是上圖裡藍藍的 top object, 對應到的 layout 就是 spinner_title_layout.xml
碰觸主體後可以展開/收起下拉式選單, 選單的 layout 是 sppiner_item_layout.xml
再透過ListView實作
從這裡可以看出, 將主體跟選單的畫面分開做就是為什麼可以做擴充型 Spinner 的原因, 丙且, 選擇的結果可以在主體作相對應的變化
因此主體本身也是一個View, View本身包含需要的Listener還有一些基本功能
基於個人喜好, 我使用RelativeLayout去做設置
簡單來說長成這樣
public class ListSpinner extends RelativeLayout
{
public enum SpinnerType
{
STRING_SPINNER,
RADIO_TOGGLE_SPINNER //with toggle button + single selection
}
private class ListAdapter extends ArrayAdapter
{
String[] list;
int mHolderViewId;
int mLayoutResource;
SpinnerType mSpinnerType;
@SuppressWarnings("unchecked")
public ListAdapter(Context context, int resource, String[] list, SpinnerType type)
{
super(context, resource, list);
this.list = list;
this.mLayoutResource = resource;
this.mSpinnerType = type;
this.mHolderViewId = getResourceIDByName(mActivity, ResourceType.Id,"dropdownTxt");
getListButtonByType(type);
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
View row = convertView;
if (row == null)
{
LayoutInflater inflater = mActivity.getLayoutInflater();
row = inflater.inflate(mLayoutResource, parent, false);
}
String desList = list[position];
updateListBackground(row, position);
RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(400, LayoutParams.MATCH_PARENT);
rlp.setMargins(10, 0, 0, 0);
TextView name = (TextView) row.findViewById(mHolderViewId);
name.setLayoutParams(rlp);
name.setText(desList);
name.setTag(desList);
updateListTriggerByType(row, this.mSpinnerType, desList);
return row;
}
}
public ListSpinner(Context context, AttributeSet attrs)
{
super(context, attrs);
mActivity = null;
mContext = context;
mSpinnerTitle = DynamicViewUtil.getViewById(this, "spinnerTitle");
mIsExpanding = false;
}
}
首先定義之後可以使用的Type
並且完成下拉式選單用的Adapter
為了讓使用這個元件可以更快速地加入每個選項的文字, 我選擇ArrayAdapter
然後做出簡單的建構子
考慮到在實用上, 不同的spinner會需要有不同的 top column 和 item
因此需要再加入兩個函數:setTitle 和 setItems
public void setTitle(final Activity activity, String titleLayout, String title)
{
mActivity = activity;
int id = getResourceIDByName(mActivity, ResourceType.Layout, titleLayout);
View view = inflate(mContext, id, null);
addView(view);
ListSpinner.LayoutParams llp = new ListSpinner.LayoutParams(400, LayoutParams.MATCH_PARENT);
llp.setMargins(10, 0, 0, 0);
mSpinnerTitle = getViewById(this, "spinnerTitle");
mSpinnerTitle.setLayoutParams(llp);
mSpinnerTitle.setText(title);
mSpinnerList = new ListView(mContext);
}
/**
* set up your spinner row content with provided listItems, layout, and pointed spinner type.
* @param listItem The String list for spinner row item.
* @param layoutResource Layout for spinner itself.
* @param type Spinner presenting style.
* */
public void setItems(String[] listItems, int layoutResource, SpinnerType type)
{
mListAdapter = new ListAdapter(mContext, layoutResource, listItems, type);
mSpinnerList.setAdapter(mListAdapter);
}
可以看到我在 setTitle 的地方才去實作下拉式選單 mSpinnerList
在 setItem 的時候, 就能產生不同類型的 spinner
基本上Spinner的主體大約就是長這樣
當然我刪掉了很多不需要講解的source 因此看起來有些缺東缺西
接下來會繼續補上 Spinner其他的函式成員, 作為Listener的Interface, 兩個Spinner Layout 和 簡單Demo最後的使用方法

沒有留言:
張貼留言