早前曾经写过一篇文章TabWidget去除底部下划线 介绍了关于TabWidget去除底部下划线功能的,当时写的比较仓促,代码比较乱,主要是将android Tabhost采用反射机制替换了原来的下划线背景从而达到去除底部下滑线的功能。Tabhost控件是放在顶部,随着android UI设计的成熟,越来越多的菜单放在了底部,这样更符合用户习惯。图-1的底部菜单布局比较常见的android UI设计。
现在将这样的常用功能整理出来,便于以后更快捷的开发相关的程序,如图-1。
图-1 常用的底部菜单布局
BottomMenuActivity是主要的类,实现了Tabhost的初始化,去除底部下线,事件改变响应等功能,至于其它的5个Activity都是简单的显示功能,如HomeActivity类。项目的布局文件也比较简单,是常用的Tabhost布局内容,图片资源比较多。
源代码:
1.BottomMenuActivity.java
package com.bottommenu.main; import java.lang.reflect.Field; import android.app.TabActivity; import android.content.Intent; import android.content.res.Resources.NotFoundException; import android.os.Build; import android.os.Bundle; import android.view.View; import android.widget.TabHost; import android.widget.TabWidget; import android.widget.TextView; import android.widget.TabHost.OnTabChangeListener; public class BottomMenuActivity extends TabActivity { TabHost mTabHost; TabWidget tabWidget; //标签 private static final String TAG_BELL = "Home"; private static final String TAG_SINGLE = "Mail"; private static final String TAG_DRAWROUNT = "User"; private static final String TAG_SETTING = "Search"; private static final String TAG_MORE = "More"; //跳转的Activity private Intent home; private Intent mail; private Intent user; private Intent search; private Intent more; //定义的width height private static final int width=0; private static final int height=50; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); setTabhost(); } //设置tabhost private void setTabhost(){ this.mTabHost = getTabHost(); home = new Intent(this, HomeActivity.class); mail = new Intent(this, MailActivity.class); user = new Intent(this, UserActivity.class); search = new Intent(this, SearchActivity.class); more = new Intent(this, MoreActivity.class); mTabHost.addTab(buildTabSpec(TAG_BELL,R.string.home,R.drawable.icon_1_n,home)); mTabHost.addTab(buildTabSpec(TAG_SINGLE,R.string.mail,R.drawable.icon_2_n,mail)); mTabHost.addTab(buildTabSpec(TAG_DRAWROUNT,R.string.user,R.drawable.icon_3_n,user)); mTabHost.addTab(buildTabSpec(TAG_SETTING,R.string.search,R.drawable.icon_4_n,search)); mTabHost.addTab(buildTabSpec(TAG_MORE,R.string.more,R.drawable.icon_5_n,more)); mTabHost.setOnTabChangedListener(change); //反射 Field mBottomLeftStrip; Field mBottomRightStrip; tabWidget = mTabHost.getTabWidget(); for (int i = 0; i < tabWidget.getChildCount(); i++) { tabWidget.getChildAt(i).getLayoutParams().width = width; tabWidget.getChildAt(i).getLayoutParams().height = height; TextView text = (TextView) tabWidget.getChildAt(i).findViewById(android.R.id.title); text.setTextColor(this.getResources().getColorStateList(android.R.color.white)); try { if (Float.valueOf(Build.VERSION.RELEASE.substring(0, 3)) <= 2.1) { mBottomLeftStrip = tabWidget.getClass().getDeclaredField("mBottomLeftStrip"); mBottomRightStrip = tabWidget.getClass().getDeclaredField("mBottomRightStrip"); } else { mBottomLeftStrip = tabWidget.getClass().getDeclaredField("mLeftStrip"); mBottomRightStrip = tabWidget.getClass().getDeclaredField("mRightStrip"); } if (!mBottomLeftStrip.isAccessible()) mBottomLeftStrip.setAccessible(true); if (!mBottomRightStrip.isAccessible()) mBottomRightStrip.setAccessible(true); //去除底部下划线 mBottomLeftStrip.set(tabWidget, getResources().getDrawable(R.drawable.no)); mBottomRightStrip.set(tabWidget, getResources().getDrawable(R.drawable.no)); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } //设置的背景 View v = tabWidget.getChildAt(i); if (mTabHost.getCurrentTab() == i) { v.setBackgroundDrawable(getResources().getDrawable(R.drawable.home_btn_bg)); } else { v.setBackgroundDrawable(getResources().getDrawable(R.drawable.no)); } } } //添加Activity private TabHost.TabSpec buildTabSpec(String tag, int resLabel, int resIcon, final Intent content) { return this.mTabHost.newTabSpec(tag).setIndicator(getString(resLabel), getResources().getDrawable(resIcon)).setContent(content); } //选项改变事件 OnTabChangeListener change = new OnTabChangeListener() { @Override public void onTabChanged(String tabId) { // TODO Auto-generated method stub mTabHost.setCurrentTabByTag(tabId); for (int i = 0; i < tabWidget.getChildCount(); i++) { View v = tabWidget.getChildAt(i); if (mTabHost.getCurrentTab() == i) { v.setBackgroundDrawable(getResources().getDrawable(R.drawable.home_btn_bg)); } else { v.setBackgroundDrawable(getResources().getDrawable(R.drawable.no)); } } } }; }
2.HomeActivity.java
package com.bottommenu.main; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; public class HomeActivity extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); TextView home=new TextView(this); home.setText(R.string.home); setContentView(home); } }
3.main.xml
<?xml version="1.0" encoding="utf-8"?> <TabHost xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/tabhost" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1.0"/> <TabWidget android:id="@android:id/tabs" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="0.0" android:layout_gravity="center_vertical" android:background="@drawable/maintab_toolbar_bg" android:paddingTop="1dp"> </TabWidget></LinearLayout> </TabHost>
4.AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.bottommenu.main" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="7" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".BottomMenuActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="com.bottommenu.main.HomeActivity"/> <activity android:name="com.bottommenu.main.MailActivity"/> <activity android:name="com.bottommenu.main.UserActivity"/> <activity android:name="com.bottommenu.main.SearchActivity"/> <activity android:name="com.bottommenu.main.MoreActivity"/> </application> </manifest>
5.string.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello World, BottomMenuActivity!</string> <string name="app_name">BottomMenu</string> <string name="home">首页</string> <string name="mail">邮箱</string> <string name="user">用户</string> <string name="search">搜索</string> <string name="more">更多</string> </resources>
6.home_btn_bg.xml
<?xml version="1.0" encoding="UTF-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_focused="true" android:state_enabled="true" android:state_pressed="false" android:drawable="@drawable/home_btn_bg_s" /> <item android:state_enabled="true" android:state_pressed="false" android:drawable="@drawable/home_btn_bg_d" /> <item android:state_enabled="true" android:state_pressed="true" android:drawable="@drawable/home_btn_bg_s" /> </selector>
源码下载:BottomMunu.zip