今天還是來講下Tab的實現。Android自帶的Tab在有比較多條目的時候會顯得非常擠,這樣不僅不美觀,更加影響操作。如果Tab能做成左右滑動的,那就非常好了。其實實現這種效果並不難,而且方法也不少。今天給大家介紹下用gallery這個組件來實現的方法。
首先我們需要寫Gallery的適配器。這裡我們要注意的是Gallery有一個特點,就是起始一個元素的左邊會留下一塊空位,如下圖所示:
這樣我們的Tab顯然不是很完美,如何解決?開始想的就是去看gallery的源碼,重寫他。不過既然我們做的是滑動的,讓他左右都可滑動不就ok了?要實現左右滑動,要做的事情就是讓裡面的元素循環。Gallery是即時顯示圖像的,可以通過兩點來做到:
1.讓getCount()方法返回一個非常大的值。
2.在getView()中顯示的時候通過循環取余來實現一直顯示數組中的有限值。
而且Gallery還提供了一個setSelection()方法,用來設置當前選擇的條目,我們將顯示的位置放在比較靠後的位置,這樣就不會在左滑的時候滑到頭,那樣就可以以假亂真了。
下面來看下適配器代碼:
- public class TabAdapter extends BaseAdapter {
- private Context mContext;
- private List<String> mList;
- private int mSelectedTab;
- public TabAdapter(Context context, List<String> list) {
- mContext = context;
- /*使用attrs裡的 <declare-styleable>屬性*/
- TypedArray a = obtainStyledAttributes(R.styleable.Gallery);
- a.recycle();//重復使用對象的styleable屬性
- if (list == null)
- list = Collections.emptyList();
- mList = list;
- }
- /*
- * 設置選中的Tab,並且刷新界面
- */
- public void setSelectedTab(int tab) {
- if (tab != mSelectedTab) {
- mSelectedTab = tab;
- notifyDataSetChanged();
- }
- }
-
- public int getSelectedTab() {
- return mSelectedTab;
- }
- public int getCount() {
- return Integer.MAX_VALUE;//返回最大值
- }
- public Object getItem(int position) {
- return mList.get(position);
- }
- public long getItemId(int position) {
- return position;
- }
- public View getView(int position, View convertView, ViewGroup parent) {
- TextView text = null;//這裡只放一個TextView,可以根據需要來定制
- if (convertView == null ) {
- text = new TextView(mContext);
- } else {
- text = (TextView) convertView;
- }
-
- text.setTextColor(Color.WHITE);
- text.setText(mList.get(position % mList.size()));//循環取余設置顯示內容
-
- text.setLayoutParams(new Gallery.LayoutParams(102, 40));
- text.setGravity(Gravity.CENTER);
-
- /*
- * 對於選中的Tab,給他一個選中的背景
- */
- if (position == mSelectedTab)
- text.setBackgroundResource(R.drawable.tab_button_select);
- else
- text.setBackgroundResource(R.drawable.tab_button_unselect);
-
- return text;
- }
- }
注釋已經寫的很清楚了,應該沒什麼問題。
這裡程序中使用了
[java]
- TypedArray a = obtainStyledAttributes(R.styleable.Gallery);
- a.recycle();//重復使用對象的styleable屬性
這是一個引用自制layout 元素的用法,必須在res/values 下面添加一個attrs.xml,並在其中定義 <declare-styleable> 標簽TAG,目的是自定義layout 的背景風格,並且通過TypeArray 的特性,讓相同的Layout 元素可以重復用於每一張圖片,大家可以看下apiDemos裡gallery1s的用法,這裡也是參考它的用法。看下attrs.xml的代碼:
[xhtml]
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <declare-styleable name="Gallery">
- <attr name="android:galleryItemBackground" />
- </declare-styleable>
- </resources>
還要說一點的是,對於選中和未選中的背景處理。我們在onItemClick中得到選中的Tab,然後為選中的和未選中的設置一個背景。這個背景這裡用自定義圖形shape的方法來定義,在res/drawable下新建xml文件,tab_button_select.xml中內容如下:
[xhtml]
- <?xml version="1.0" encoding="utf-8"?>
- <shape xmlns:android="http://schemas.android.com/apk/res/android">
- <gradient android:startColor="#FFA2A2A2" android:endColor="#FF5F5F5F"
- android:angle="90.0">
- </gradient>
- </shape>
其中的gradient標簽實現一個從startColor到endColor角度為90漸變色。其實我們經常用這種方式來自定義我們的控件,可以用來實現圓角,漸變,描邊等效果,分別在shape根節點下用gradient,corners,stroke標簽實現,大家可以自己去試試,效果還是很好的,也很簡單。
下面來看下MainActivity的代碼,顯示layout的方法和我以前一篇仿Iphone效果的Tab中一樣,通過隱藏和顯示相應的layout來實現。當然,也可以通過intent來指向不同的Activity等方法來做。注意定義要顯示的Tab數組的時候,因為我們第一個顯示的不是第一個Tab,所以適當調整下數組的定義順序,同樣對應的layou也是。
[java]
- public class MainActivity extends Activity {
- private Gallery gallery;
- private TabAdapter textAdapter;
- private static final String[] TAB_NAMES = {
-
- "第四個",
- "第一個",
- "第二個",
- "第三個",
- };//注意調整順序
-
- private LinearLayout mTabLayout_One;
- private LinearLayout mTabLayout_Two;
- private LinearLayout mTabLayout_Three;
- private LinearLayout mTabLayout_Four;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
- gallery = (Gallery) findViewById(R.id.gallery);
- textAdapter = new TabAdapter(this, Arrays.asList(TAB_NAMES));
- gallery.setAdapter(textAdapter);
- gallery.setSelection(34);//這裡根據你的Tab數自己算一下,讓左邊的稍微多一點,不要一滑就滑到頭
-
- mTabLayout_One = (LinearLayout) this.findViewById( R.id.TabLayout_One );
- mTabLayout_Two = (LinearLayout) this.findViewById( R.id.TabLayout_Two );
- mTabLayout_Three = (LinearLayout) this.findViewById( R.id.TabLayout_Three );
- mTabLayout_Four = (LinearLayout) this.findViewById( R.id.TabLayout_Four );
-
- mTabLayout_One.setVisibility( View.GONE );
- mTabLayout_Two.setVisibility( View.VISIBLE );
- mTabLayout_Three.setVisibility( View.GONE );
- mTabLayout_Four.setVisibility( View.GONE );
-
- gallery.setOnItemClickListener(new OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position,
- long id) {
- TabAdapter adapter = (TabAdapter)parent.getAdapter();
- adapter.setSelectedTab(position);
- switch(position %TAB_NAMES.length ){
- case 0:
- mTabLayout_One.setVisibility( View.VISIBLE );
- mTabLayout_Two.setVisibility( View.GONE );
- mTabLayout_Three.setVisibility( View.GONE );
- mTabLayout_Four.setVisibility( View.GONE );
- break;
- case 1:
- mTabLayout_One.setVisibility( View.GONE );
- mTabLayout_Two.setVisibility( View.VISIBLE );
- mTabLayout_Three.setVisibility( View.GONE );
- mTabLayout_Four.setVisibility( View.GONE );
- break;
- case 2:
- mTabLayout_One.setVisibility( View.GONE );
- mTabLayout_Two.setVisibility( View.GONE );
- mTabLayout_Three.setVisibility( View.VISIBLE );
- mTabLayout_Four.setVisibility( View.GONE );
- break;
- case 3:
- mTabLayout_One.setVisibility( View.GONE );
- mTabLayout_Two.setVisibility( View.GONE );
- mTabLayout_Three.setVisibility( View.GONE );
- mTabLayout_Four.setVisibility( View.VISIBLE );
- }
- }
-
- });
-
- }