最近有很多事情要忙,一直没有更新博客,今天得空来写一写。话说春天什么时候来,还是冷兮兮的。

今天还是来讲下Tab的实现。android自带的Tab在有比较多条目的时候会显得非常挤,这样不仅不美观,更加影响操作。如果Tab能做成左右滑动的,那就非常好了。其实实现这种效果并不难,而且方法也不少。今天给大家介绍下用gallery这个组件来实现的方法。

首先我们需要写Gallery的适配器。这里我们要注意的是Gallery有一个特点,就是起始一个元素的左边会留下一块空位,如下图所示:

 

这样我们的Tab显然不是很完美,如何解决?开始想的就是去看gallery的源码,重写他。不过既然我们做的是滑动的,让他左右都可滑动不就ok了?要实现左右滑动,要做的事情就是让里面的元素循环。Gallery是即时显示图像的,可以通过两点来做到:

  1.让getCount()方法返回一个非常大的值。

  2.在getView()中显示的时候通过循环取余来实现一直显示数组中的有限值。

  而且Gallery还提供了一个setSelection()方法,用来设置当前选择的条目,我们将显示的位置放在比较靠后的位置,这样就不会在左滑的时候滑到头,那样就可以以假乱真了。

  下面来看下适配器代码:

 
  
  1. public class TabAdapter extends BaseAdapter {  
  2.  private Context mContext;  
  3.  private List<String> mList;  
  4.  private int mSelectedTab;  
  5.  
  6.  public TabAdapter(Context context, List<String> list) {  
  7.  mContext = context;  
  8.  /*使用attrs里的 <declare-styleable>属性*/ 
  9.  TypedArray a = obtainStyledAttributes(R.styleable.Gallery);  
  10.  a.recycle();//重复使用对象的styleable属性  
  11.    if (list == null)  
  12.  list = Collections.emptyList();  
  13.  mList = list;  
  14.  }  
  15.  /*  
  16.  * 设置选中的Tab,并且刷新界面  
  17.  */ 
  18.  public void setSelectedTab(int tab) {  
  19.  if (tab != mSelectedTab) {  
  20.  mSelectedTab = tab;  
  21.  notifyDataSetChanged();  
  22.  }  
  23.  }  
  24.  
  25.  public int getSelectedTab() {  
  26.  return mSelectedTab;  
  27.  }  
  28.  
  29.  public int getCount() {  
  30.  return Integer.MAX_VALUE;//返回最大值  
  31.    }  
  32.  
  33.  public Object getItem(int position) {  
  34.  return mList.get(position);  
  35.  }  
  36.  
  37.  public long getItemId(int position) {  
  38.  return position;  
  39.  }  
  40.  
  41.  public View getView(int position, View convertView, ViewGroup parent) {  
  42.  TextView text = null;//这里只放一个TextView,可以根据需要来定制  
  43.    if (convertView == null ) {  
  44.  text = new TextView(mContext);  
  45.  } else {  
  46.  text = (TextView) convertView;  
  47.  }  
  48.  
  49.  text.setTextColor(Color.WHITE);  
  50.  text.setText(mList.get(position % mList.size()));//循环取余设置显示内容  
  51.     
  52.  text.setLayoutParams(new Gallery.LayoutParams(10240));  
  53.  text.setGravity(Gravity.CENTER);  
  54.  
  55.  /*  
  56.  * 对于选中的Tab,给他一个选中的背景  
  57.  */ 
  58.  if (position == mSelectedTab)  
  59.  text.setBackgroundResource(R.drawable.tab_button_select);  
  60.  else 
  61.  text.setBackgroundResource(R.drawable.tab_button_unselect);  
  62.  
  63.  return text;  
  64.  }  
  65.  } 

注释已经写的很清楚了,应该没什么问题。

这里程序中使用了

 
  
  1. TypedArray a = obtainStyledAttributes(R.styleable.Gallery);  
  2. a.recycle();//重复使用对象的styleable属性  

这是一个引用自制layout 元素的用法,必须在res/values 下面添加一个attrs.xml,并在其中定义 <declare-styleable> 标签TAG,目的是自定义layout 的背景风格,并且通过TypeArray 的特性,让相同的Layout 元素可以重复用于每一张图片,大家可以看下apiDemos里gallery1s的用法,这里也是参考它的用法。看下attrs.xml的代码:

 
  
  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <resources> 
  3. <declare-styleable name="Gallery"> 
  4. <attr name="android:galleryItemBackground" /> 
  5. </declare-styleable> 
  6. </resources> 

还要说一点的是,对于选中和未选中的背景处理。我们在onItemClick中得到选中的Tab,然后为选中的和未选中的设置一个背景。这个背景这里用自定义图形shape的方法来定义,在res/drawable下新建xml文件,tab_button_select.xml中内容如下:

 
  
  1. <?xml version="1.0" encoding="utf-8"?> 
  2.  <shape xmlns:android="http://schemas.android.com/apk/res/android"> 
  3.  <gradient android:startColor="#FFA2A2A2" android:endColor="#FF5F5F5F" 
  4.  android:angle="90.0"> 
  5.  </gradient> 
  6.  </shape> 

其中的gradient标签实现一个从startColor到endColor角度为90渐变色。其实我们经常用这种方式来自定义我们的控件,可以用来实现圆角,渐变,描边等效果,分别在shape根节点下用gradient,corners,stroke标签实现,大家可以自己去试试,效果还是很好的,也很简单。

下面来看下MainActivity的代码,显示layout的方法和我以前一篇仿Iphone效果的Tab中一样,通过隐藏和显示相应的 layout来实现。当然,也可以通过intent来指向不同的Activity等方法来做。注意定义要显示的Tab数组的时候,因为我们第一个显示的不是第一个Tab,所以适当调整下数组的定义顺序,同样对应的layou也是。

 
  
  1. public class MainActivity extends Activity {  
  2.  
  3.  private Gallery gallery;  
  4.  private TabAdapter textAdapter;  
  5.  
  6.  private static final String[] TAB_NAMES = {  
  7.  
  8.  "第四个",  
  9.  "第一个",  
  10.  "第二个",  
  11.  "第三个",  
  12.  };  
  13.  
  14.  private LinearLayout mTabLayout_One;  
  15.  private LinearLayout mTabLayout_Two;  
  16.  private LinearLayout mTabLayout_Three;  
  17.  private LinearLayout mTabLayout_Four;  
  18.  
  19.  @Override 
  20.  public void onCreate(Bundle savedInstanceState) {  
  21.  super.onCreate(savedInstanceState);  
  22.  setContentView(R.layout.main);  
  23.  
  24.  gallery = (Gallery) findViewById(R.id.gallery);  
  25.  textAdapter = new TabAdapter(this, Arrays.asList(TAB_NAMES));  
  26.  gallery.setAdapter(textAdapter);  
  27.  gallery.setSelection(34);//这里根据你的Tab数自己算一下,让左边的稍微多一点,不要一滑就滑到头  
  28.  
  29.  mTabLayout_One = (LinearLayout) this.findViewById( R.id.TabLayout_One );  
  30.  mTabLayout_Two = (LinearLayout) this.findViewById( R.id.TabLayout_Two );  
  31.  mTabLayout_Three = (LinearLayout) this.findViewById( R.id.TabLayout_Three );  
  32.  mTabLayout_Four = (LinearLayout) this.findViewById( R.id.TabLayout_Four );  
  33.  
  34.  mTabLayout_One.setVisibility( View.GONE );  
  35.  mTabLayout_Two.setVisibility( View.VISIBLE );  
  36.  mTabLayout_Three.setVisibility( View.GONE );  
  37.  mTabLayout_Four.setVisibility( View.GONE );  
  38.  
  39.  gallery.setOnItemClickListener(new OnItemClickListener() {  
  40.  
  41.  @Override 
  42.  public void onItemClick(AdapterView<?> parent, View view, int position,  
  43.  long id) {  
  44.  TabAdapter adapter = (TabAdapter)parent.getAdapter();  
  45.  adapter.setSelectedTab(position);  
  46.  switch(position %TAB_NAMES.length ){  
  47.  case 0:  
  48.  mTabLayout_One.setVisibility( View.VISIBLE );  
  49.  mTabLayout_Two.setVisibility( View.GONE );  
  50.  mTabLayout_Three.setVisibility( View.GONE );  
  51.  mTabLayout_Four.setVisibility( View.GONE );  
  52.  break;  
  53.  case 1:  
  54.  mTabLayout_One.setVisibility( View.GONE );  
  55.  mTabLayout_Two.setVisibility( View.VISIBLE );  
  56.  mTabLayout_Three.setVisibility( View.GONE );  
  57.  mTabLayout_Four.setVisibility( View.GONE );  
  58.  break;  
  59.  case 2:  
  60.  mTabLayout_One.setVisibility( View.GONE );  
  61.  mTabLayout_Two.setVisibility( View.GONE );  
  62.  mTabLayout_Three.setVisibility( View.VISIBLE );  
  63.  mTabLayout_Four.setVisibility( View.GONE );  
  64.  break;  
  65.  case 3:  
  66.  mTabLayout_One.setVisibility( View.GONE );  
  67.  mTabLayout_Two.setVisibility( View.GONE );  
  68.  mTabLayout_Three.setVisibility( View.GONE );  
  69.  mTabLayout_Four.setVisibility( View.VISIBLE );  
  70.  }  
  71.  }  
  72.  });  
  73.  }  
  74.  } 

最后就是main.xml布局文件了:

 
  
  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  3. android:orientation="vertical" android:layout_width="fill_parent" 
  4. android:layout_height="fill_parent" 
  5. android:background="#C5CCD4FF"> 
  6. <LinearLayout 
  7. android:id = "@+id/TabLayout_One" 
  8. android:layout_width = "fill_parent" 
  9. android:layout_height = "fill_parent" 
  10. android:layout_below = "@+id/gallery" 
  11. > 
  12. <TextView 
  13. android:textColor="@android:color/black" 
  14. android:textSize="30sp" 
  15. android:layout_width = "wrap_content" 
  16. android:layout_height = "wrap_content" 
  17. android:text = "这是第四个布局" 
  18. /> 
  19. </LinearLayout> 
  20.  
  21. <LinearLayout 
  22. android:id = "@+id/TabLayout_Two" 
  23. android:layout_width = "fill_parent" 
  24. android:layout_height = "fill_parent" 
  25. android:layout_below = "@+id/gallery" 
  26. > 
  27.  
  28. <Button 
  29. android:layout_width = "wrap_content" 
  30. android:layout_height = "wrap_content" 
  31. android:text = "这是第一个布局" 
  32. android:textSize = "30sp" 
  33. /> 
  34. </LinearLayout> 
  35. <LinearLayout 
  36. android:id = "@+id/TabLayout_Three" 
  37. android:layout_width = "fill_parent" 
  38. android:layout_height = "fill_parent" 
  39. android:layout_below = "@+id/gallery" 
  40. > 
  41.  
  42. <TextView 
  43. android:layout_width = "fill_parent" 
  44. android:layout_height = "fill_parent" 
  45. android:textSize="25sp" 
  46. android:textColor="#ffffff" 
  47. android:text="你觉得怎么样?" 
  48. /> 
  49. </LinearLayout> 
  50. <LinearLayout 
  51. android:id = "@+id/TabLayout_Four" 
  52. android:layout_width = "fill_parent" 
  53. android:layout_height = "fill_parent" 
  54. android:layout_below = "@+id/gallery" 
  55. > 
  56. <TextView 
  57. android:textColor="@android:color/black" 
  58. android:layout_width = "wrap_content" 
  59. android:layout_height = "wrap_content" 
  60. android:text = "很简单,是么" 
  61. /> 
  62.  
  63. </LinearLayout> 
  64. <Gallery 
  65. android:id="@+id/gallery" 
  66. android:layout_alignParentTop="true" 
  67. android:layout_width="fill_parent" 
  68. android:layout_height="wrap_content" 
  69. android:unselectedAlpha="1" 
  70. android:spacing="1dip"/> 
  71. </RelativeLayout> 

这样我们用gallery实现的可滑动的Tab就完成了,看下最后的效果。

大家有什么问题可以留言交流哈。特别是对让左边不留空的方法有好的解决办法的话,希望能提出来,大家一起学习交流。