今天把这个仿iphone效果的tab写完,这个例子参考国外rolle3k共享的代码,感谢rolle3k。
上篇博客我们写了一个Itab类,介绍了背景的绘制和简单的一个图的贴图方法。我们继续来完成Itab这个类,同时把他放到MainAcitvity(继承Activity)这个类内部,这样,整个程序只需一个类就可以了。(上篇博客例子运行需要再建一个Activity的子类来作为lanucher)。废话不多说了,看看代码
1 public static class iTab extends View
2 {
3 private Paint mPaint; // 背景画笔
4 private Paint mActiveTextPaint; // 选中
5 private Paint mInactiveTextPaint; // 未选中
6 private ArrayList < TabMember > mTabMembers; // tab成员
7 private int mActiveTab;
8 private OnTabClickListener mOnTabClickListener = null ;
9
10 public iTab( Context context, AttributeSet attrs ) // 构造器,在里面初始化画笔
11 {
12 super (context, attrs);
13
14 mTabMembers = new ArrayList < MainActivity.iTab.TabMember > ( );
15
16 mPaint = new Paint( );
17 mActiveTextPaint = new Paint( );
18 mInactiveTextPaint = new Paint( );
19
20 mPaint.setStyle( Paint.Style.FILL );
21 mPaint.setColor( 0xFFFFFF00 );
22 mPaint.setAntiAlias( true );
23
24 mActiveTextPaint.setTextAlign( Align.CENTER );
25 mActiveTextPaint.setTextSize( 12 );
26 mActiveTextPaint.setColor( 0xFFFFFFFF );
27 mActiveTextPaint.setAntiAlias( true );
28
29
30 mInactiveTextPaint.setTextAlign( Align.CENTER );
31 mInactiveTextPaint.setTextSize( 12 );
32 mInactiveTextPaint.setColor( 0xFF999999 );
33 mInactiveTextPaint.setAntiAlias( true );
34 mActiveTab = 0 ;
35
36 }
37
38 @Override
39 protected void onDraw( Canvas canvas )
40 {
41 super .onDraw( canvas );
42
43 Rect r = new Rect( );
44 this .getDrawingRect( r );
45
46 // 计算每个标签能使用多少像素
47 int singleTabWidth = r.right / ( mTabMembers.size( ) != 0 ? mTabMembers.size( ) : 1 );
48
49
50 // 绘制背景
51 canvas.drawColor( 0xFF000000 );
52 mPaint.setColor( 0xFF434343 );
53 canvas.drawLine( r.left, r.top + 1 , r.right, r.top + 1 , mPaint );
54
55 int color = 46 ;
56
57 for ( int i = 0 ; i < 24 ; i ++ )
58 {
59 mPaint.setARGB( 255 , color, color, color );
60 canvas.drawRect( r.left, r.top + i + 1 , r.right, r.top + i + 2 , mPaint );
61 color -- ;
62 }
63
64 // 绘制每一个tab
65 for ( int i = 0 ; i < mTabMembers.size( ); i ++ )
66 {
67 TabMember tabMember = mTabMembers.get( i );
68
69 Bitmap icon = BitmapFactory.decodeResource( getResources( ), tabMember.getIconResourceId( ) );
70 Bitmap iconColored = Bitmap.createBitmap( icon.getWidth(), icon.getHeight(), Bitmap.Config.ARGB_8888 );
71 Paint p = new Paint( Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
72 Canvas iconCanvas = new Canvas( );
73 iconCanvas.setBitmap( iconColored );
74
75 if ( mActiveTab == i ) // 为已选中的tab绘制一个白蓝的渐变色,未选中的绘制一个白灰的渐变色
76 {
77 p.setShader( new LinearGradient( 0 , 0 , icon.getWidth(), icon.getHeight(),
78 0xFFFFFFFF , 0xFF54C7E1 , Shader.TileMode.CLAMP ) );
79 }
80 else {
81 p.setShader( new LinearGradient( 0 , 0 , icon.getWidth(), icon.getHeight(),
82 0xFFA2A2A2 , 0xFF5F5F5F , Shader.TileMode.CLAMP ) );
83 }
84
85 iconCanvas.drawRect( 0 , 0 , icon.getWidth( ), icon.getHeight( ), p );
86
87 for ( int x = 0 ; x < icon.getWidth(); x ++ )
88 {
89 for ( int y = 0 ; y < icon.getHeight(); y ++ )
90 {
91 if ( ( icon.getPixel(x, y) & 0xFF000000 ) == 0 )
92 {
93 iconColored.setPixel( x, y, 0x00000000 );
94 }
95 }
96 }
97
98 // 计算tab图片的位置
99 int tabImgX = singleTabWidth * i + ( singleTabWidth / 2 - icon.getWidth( ) / 2 );
100
101 // 绘制tab图片 选中的和未选中的
102 if ( mActiveTab == i )
103 {
104 mPaint.setARGB( 37 , 255 , 255 , 255 );
105 canvas.drawRoundRect( new RectF( r.left + singleTabWidth * i + 3 , r.top + 3 ,
106 r.left + singleTabWidth * ( i + 1 ) - 3 , r.bottom - 2 ), 5 , 5 , mPaint );
107 canvas.drawBitmap( iconColored, tabImgX , r.top + 5 , null );
108 canvas.drawText( tabMember.getText( ),
109 singleTabWidth * i + ( singleTabWidth / 2 ), r.bottom - 2 , mActiveTextPaint );
110 } else
111 {
112 canvas.drawBitmap( iconColored, tabImgX , r.top + 5 , null );
113 canvas.drawText( tabMember.getText( ),
114 singleTabWidth * i + ( singleTabWidth / 2 ), r.bottom - 2 , mInactiveTextPaint );
115 }
116 }
117
118 }
119 /*
120 * 触摸事件
121 */
122 @Override
123 public boolean onTouchEvent( MotionEvent motionEvent )
124 {
125 Rect r = new Rect( );
126 this .getDrawingRect( r );
127 float singleTabWidth = r.right / ( mTabMembers.size( ) != 0 ? mTabMembers.size( ) : 1 );
128
129 int pressedTab = ( int ) ( ( motionEvent.getX( ) / singleTabWidth ) - ( motionEvent.getX( ) / singleTabWidth ) % 1 );
130
131 mActiveTab = pressedTab;
132
133 if ( this .mOnTabClickListener != null )
134 {
135 this .mOnTabClickListener.onTabClick( mTabMembers.get( pressedTab ).getId( ) );
136 }
137
138 this .invalidate();
139
140 return super .onTouchEvent( motionEvent );
141 }
142
143 void addTabMember( TabMember tabMember )
144 {
145 mTabMembers.add( tabMember );
146 }
147
148 void setOnTabClickListener( OnTabClickListener onTabClickListener )
149 {
150 mOnTabClickListener = onTabClickListener;
151 }
152
153 public static class TabMember // 处理tab成员
154 {
155 protected int mId;
156 protected String mText;
157 protected int mIconResourceId;
158
159 TabMember( int Id, String Text, int iconResourceId )
160 {
161 mId = Id;
162 mIconResourceId = iconResourceId;
163 mText = Text;
164 }
165
166 public int getId( )
167 {
168 return mId;
169 }
170
171 public String getText( )
172 {
173 return mText;
174 }
175
176 public int getIconResourceId( )
177 {
178 return mIconResourceId;
179 }
180
181 public void setText( String Text )
182 {
183 mText = Text;
184 }
185
186 public void setIconResourceId( int iconResourceId )
187 {
188 mIconResourceId = iconResourceId;
189 }
190 }
191
192 public static interface OnTabClickListener
193 {
194 public abstract void onTabClick( int tabId );
195 }
196 }
这是MainActivity这个类里面的两个static类,看我写的注释和上篇博客的内容应该都能理解。其中还定义了触摸事件,实现点击tab出现不同布局的效果。接下来我们只需要在我们的layout上添加就可以了,我们继续写一个内部类
1 public static class iRelativeLayout extends RelativeLayout // 注意,还是声明为静态
2 {
3 private Paint mPaint;
4 private Rect mRect;
5
6 public iRelativeLayout( Context context, AttributeSet attrs )
7 {
8 super (context, attrs);
9
10 mRect = new Rect( );
11 mPaint = new Paint( );
12
13 mPaint.setStyle( Paint.Style.FILL_AND_STROKE );
14 mPaint.setColor( 0xFFCBD2D8 );
15 }
16
17 @Override
18 protected void onDraw( Canvas canvas )
19 {
20 super .onDraw( canvas );
21
22 canvas.drawColor( 0xFFC5CCD4 );
23
24 this .getDrawingRect( mRect );
25
26 for ( int i = 0 ; i < mRect.right; i += 7 ) // 绘制屏幕背景的纹理效果
27 {
28 canvas.drawRect( mRect.left + i, mRect.top, mRect.left + i + 2 , mRect.bottom, mPaint );
29 }
30
31 }
32 }
33
34
35 private static final int TAB_HIGHLIGHT = 1 ;
36 private static final int TAB_CHAT = 2 ;
37 private static final int TAB_LOOPBACK = 3 ;
38 private static final int TAB_REDO = 4 ;
39 private iTab mTabs;
40 private LinearLayout mTabLayout_One;
41 private LinearLayout mTabLayout_Two;
42 private LinearLayout mTabLayout_Three;
43 private LinearLayout mTabLayout_Four;
44 private LinearLayout mTabLayout_Five;
45
46 @Override
47 public void onCreate(Bundle savedInstanceState)
48 {
49 super .onCreate(savedInstanceState);
50 setContentView(R.layout.main);
51
52
53 mTabs = (iTab) this .findViewById( R.id.Tabs );
54 mTabLayout_One = (LinearLayout) this .findViewById( R.id.TabLayout_One );
55 mTabLayout_Two = (LinearLayout) this .findViewById( R.id.TabLayout_Two );
56 mTabLayout_Three = (LinearLayout) this .findViewById( R.id.TabLayout_Three );
57 mTabLayout_Four = (LinearLayout) this .findViewById( R.id.TabLayout_Four );
58 mTabLayout_Five = (LinearLayout) this .findViewById( R.id.TabLayout_Four ); // 偷个懒,不写第五个界面啦
59
60 mTabs.addTabMember( new TabMember( TAB_HIGHLIGHT, " 精选 " , R.drawable.jingxuan ) );
61 mTabs.addTabMember( new TabMember( TAB_CHAT, " 类别 " , R.drawable.cat ) );
62 mTabs.addTabMember( new TabMember( TAB_LOOPBACK, " 25大排行榜 " , R.drawable.rank ) );
63 mTabs.addTabMember( new TabMember( TAB_REDO, " 搜索 " , R.drawable.search ) );
64 mTabs.addTabMember( new TabMember( TAB_REDO, " 更新 " , R.drawable.download ) ); // 添加tab
65
66 /* 初始显示第一个界面 */
67 mTabLayout_One.setVisibility( View.VISIBLE );
68 mTabLayout_Two.setVisibility( View.GONE );
69 mTabLayout_Three.setVisibility( View.GONE );
70 mTabLayout_Four.setVisibility( View.GONE );
71
72 mTabs.setOnTabClickListener( new OnTabClickListener( ) {
73 @Override
74 public void onTabClick( int tabId ) // 实现点击事件
75 {
76 if ( tabId == TAB_HIGHLIGHT )
77 {
78 mTabLayout_One.setVisibility( View.VISIBLE );
79 mTabLayout_Two.setVisibility( View.GONE );
80 mTabLayout_Three.setVisibility( View.GONE );
81 mTabLayout_Four.setVisibility( View.GONE );
82 } else if ( tabId == TAB_CHAT )
83 {
84 mTabLayout_One.setVisibility( View.GONE );
85 mTabLayout_Two.setVisibility( View.VISIBLE );
86 mTabLayout_Three.setVisibility( View.GONE );
87 mTabLayout_Four.setVisibility( View.GONE );
88 } else if ( tabId == TAB_LOOPBACK )
89 {
90 mTabLayout_One.setVisibility( View.GONE );
91 mTabLayout_Two.setVisibility( View.GONE );
92 mTabLayout_Three.setVisibility( View.VISIBLE );
93 mTabLayout_Four.setVisibility( View.GONE );
94 } else if ( tabId == TAB_REDO )
95 {
96 mTabLayout_One.setVisibility( View.GONE );
97 mTabLayout_Two.setVisibility( View.GONE );
98 mTabLayout_Three.setVisibility( View.GONE );
99 mTabLayout_Four.setVisibility( View.VISIBLE );
100 }
101 }
102 });
103 }
其中onDraw()方法里面实现了背景的纹理效果,配合xml里面背景色的配置,实现了如下图所示的效果:
是不是非常漂亮呢。下面就是xml里面的配置了
1 <? xml version="1.0" encoding="utf-8" ?>
2
3 < view xmlns:android ="http://schemas.android.com/apk/res/android"
4 class ="com.notice520.MainActivity$iRelativeLayout"
5 android:orientation ="vertical"
6 android:layout_width ="fill_parent"
7 android:layout_height ="fill_parent"
8 android:background = "#C5CCD4FF"
9 >
10 < LinearLayout
11 android:id = "@+id/TabLayout_One"
12 android:layout_width = "fill_parent"
13 android:layout_height = "fill_parent"
14 android:layout_above = "@+id/Tabs"
15 >
16 < ScrollView android:layout_width ="fill_parent" android:layout_height ="wrap_content" >
17 < RelativeLayout
18 android:layout_width = "fill_parent"
19 android:layout_height = "fill_parent"
20 android:visibility = "visible"
21 >
22 < TextView
23 android:textColor ="@android:color/black"
24 android:textSize ="30sp"
25 android:layout_width = "wrap_content"
26 android:layout_height = "wrap_content"
27 android:text = "春节快乐!!"
28 />
29 </ RelativeLayout >
30 </ ScrollView >
31 </ LinearLayout >
32
33 < LinearLayout
34 android:id = "@+id/TabLayout_Two"
35 android:layout_width = "fill_parent"
36 android:layout_height = "fill_parent"
37 android:layout_above = "@+id/Tabs"
38 >
39 < ScrollView android:layout_width ="fill_parent" android:layout_height ="wrap_content" >
40 < RelativeLayout
41 android:layout_width = "fill_parent"
42 android:layout_height = "fill_parent"
43 android:visibility = "visible"
44 android:layout_above = "@+id/Tabs"
45 >
46 < Button
47 android:layout_width = "wrap_content"
48 android:layout_height = "wrap_content"
49 android:text = "祝大家事业有成!"
50 android:textSize = "30sp"
51 />
52 </ RelativeLayout >
53 </ ScrollView >
54 </ LinearLayout >
55 < LinearLayout
56 android:id = "@+id/TabLayout_Three"
57 android:layout_width = "fill_parent"
58 android:layout_height = "fill_parent"
59 android:layout_above = "@+id/Tabs"
60 >
61 < ScrollView android:layout_width ="fill_parent" android:layout_height ="wrap_content" >
62 < RelativeLayout
63 android:layout_width = "fill_parent"
64 android:layout_height = "fill_parent"
65 android:visibility = "visible"
66 android:layout_above = "@+id/Tabs"
67 >
68 < ImageView
69
70 android:layout_width = "fill_parent"
71 android:layout_height = "fill_parent"
72 android:src ="@drawable/newq"
73 />
74 </ RelativeLayout >
75 </ ScrollView >
76 </ LinearLayout >
77 < LinearLayout
78 android:id = "@+id/TabLayout_Four"
79 android:layout_width = "fill_parent"
80 android:layout_height = "fill_parent"
81 android:layout_above = "@+id/Tabs"
82 >
83 < ScrollView android:layout_width ="fill_parent" android:layout_height ="wrap_content" >
84 < RelativeLayout
85 android:id = "@+id/TabLayout_Four"
86 android:layout_width = "fill_parent"
87 android:layout_height = "fill_parent"
88 android:visibility = "visible"
89 android:layout_above = "@+id/Tabs"
90 >
91 < TextView
92 android:textColor ="@android:color/black"
93 android:layout_width = "wrap_content"
94 android:layout_height = "wrap_content"
95 android:text = "很简单,是么"
96 />
97 </ RelativeLayout >
98 </ ScrollView >
99 </ LinearLayout >
100 < view
101 class ="com.notice520.MainActivity$iTab"
102 android:id ="@+id/Tabs"
103 android:layout_width = "fill_parent"
104 android:layout_height = "49px"
105 android:layout_alignParentBottom = "true"
106 />
107 </ view >
108
来看看最终的效果吧
是不是还不错呢 希望大家喜欢,有问题可以留言交流。