[转载]android UI进阶之仿iphone的tab效果(二) – noTice520 – 博客园.
今天把这个仿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
来看看最终的效果吧
是不是还不错呢 希望大家喜欢,有问题可以留言交流。