您好,登錄后才能下訂單哦!
今天,我將總結一下Android應用中大家經常見到的底部導航欄的幾種實現!
一。TabHost + RadioGroup實現方式
在我們平時開發過程中使用的TabHost是在上方,這里我們簡單修改了一下<TabHost>的布局,讓葉片放到了底部。
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" android:orientation="horizontal" > <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TabWidget android:id="@android:id/tabs" android:layout_width="fill_parent" android:layout_height="wrap_content" android:visibility="gone" /> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1.0" /> <RadioGroup android:id="@+id/radioGroup" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:background="@drawable/bar" android:gravity="center_vertical" android:orientation="horizontal" > <RadioButton android:id="@+id/rd_home" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableTop="@drawable/home_icon" android:text="主頁" /> <RadioButton android:id="@+id/rd_wt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableTop="@drawable/wb_icon_write_n" android:text="發表" /> <RadioButton android:id="@+id/rd_msg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableTop="@drawable/msg_icon" android:text="信息" /> <RadioButton android:id="@+id/rd_more" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableTop="@drawable/more_icon" android:text="更多" /> </RadioGroup> </LinearLayout> </TabHost>
styles.xml
<style name="main_btn_style"> <item name="android:button">@null</item> <item name="android:textSize">10dp</item> <item name="android:textColor">#ffffff</item> <item name="android:gravity">center_horizontal</item> <item name="android:drawablePadding">4dp</item> <item name="android:layout_weight">1.0</item> <item name="android:background">@drawable/main_btn_bg_d</item> </style>
main_btn_bg_d.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/main_btn_bg" android:state_enabled="true" android:state_pressed="true"></item> <item android:drawable="@drawable/main_btn_bg" android:state_checked="true" android:state_enabled="true"></item> </selector>
這里需要注意的是:
1.main.xml中:TabWidget的id必須是@android:id/tabs,FrameLayout的id必須是 @android:id/tabcontent。
2.把TabWidget的Visibility設置成了gone!也就是默認難看的風格不見了:,取而代之的是5個帶風格的單選按鈕.
MainActivity類
package com.zhf.android_tabhost; import android.app.TabActivity; import android.content.Intent; import android.os.Bundle; import android.widget.RadioGroup; import android.widget.RadioGroup.OnCheckedChangeListener; import android.widget.TabHost; import android.widget.TabHost.TabSpec; public class MainActivity extends TabActivity { private TabHost tabHost; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); tabHost = this.getTabHost(); TabSpec homeSpec = tabHost.newTabSpec("home").setIndicator("home").setContent(new Intent(this,HomeActivity.class)); TabSpec writeSpec = tabHost.newTabSpec("write").setIndicator("write").setContent(new Intent(this,WriteActivity.class)); TabSpec msgSpec = tabHost.newTabSpec("msg").setIndicator("msg").setContent(new Intent(this,MsgActivity.class)); TabSpec moreSpec = tabHost.newTabSpec("more").setIndicator("more").setContent(new Intent(this,MoreActivity.class)); tabHost.addTab(homeSpec); tabHost.addTab(writeSpec); tabHost.addTab(msgSpec); tabHost.addTab(moreSpec); RadioGroup rg = (RadioGroup) this.findViewById(R.id.radioGroup); rg.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group, int checkedId) { switch (checkedId) { case R.id.rd_home: tabHost.setCurrentTabByTag("home"); break; case R.id.rd_wt: tabHost.setCurrentTabByTag("write"); break; case R.id.rd_msg: tabHost.setCurrentTabByTag("msg"); break; case R.id.rd_more: tabHost.setCurrentTabByTag("more"); break; default: break; } } }); } }
注:
1.由于TabWidget被隱藏,所以相關的事件也會無效,這里取巧用RadioGroup與RadioButton的特性來處理切換,然后監聽事件調用setCurrentTabByTag來切換Activity。
2.注意即使TabWidget被隱藏,也要為其設置indicator,否則會保持。
效果圖:
(點擊底部就可以實現切換不同的Activity的操作了,這里需要注意的一點是,切換底部菜單時不會重新調用onCreate()方法的!!)
二.底部回調接口實現(使用Fragment)--- 重要!
這種方式使用了最新的Fragment,采用了底部導航欄回調接口的方法,來切換底部菜單,并且每次切換回重新調用onCreate()方法!!
main.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" tools:context=".MainActivity" > <LinearLayout android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="10" android:orientation="vertical" > <RelativeLayout android:id="@+id/main_title_RelativeLayout" android:layout_width="fill_parent" android:layout_height="50dp" android:background="@drawable/fragment_bottom_normal" android:orientation="horizontal" > <TextView android:id="@+id/main_title_TextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="主頁" android:textColor="@android:color/white" android:textSize="24sp" /> </RelativeLayout> <FrameLayout android:id="@+id/main_detail_FrameLayout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ffffff" > </FrameLayout> </LinearLayout> <fragment android:id="@+id/bottom_fragment" android:name="com.zhf.frameworkdemo02.fragments.BottomFragment" android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1" /> </LinearLayout>
這里由于我們底部菜單我們采用了fragment,所以布局里面要留出位置!
BottomFragment類:
package com.zhf.frameworkdemo02.fragments; import com.zhf.frameworkdemo02.R; import android.app.Activity; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.RadioGroup; import android.widget.RadioGroup.OnCheckedChangeListener; /** * 頁面底部導航欄 * * @author ZHF * */ public class BottomFragment extends Fragment { //默認回調接口實現類的對象 private Callbacks callbacks = defaultCallbacks; /** Fragment和Activity建立關聯的時候調用 **/ @Override public void onAttach(Activity activity) { super.onAttach(activity); //當前類是否實現了底部導航欄點擊事件回調接口 if(!(activity instanceof Callbacks)) { throw new IllegalStateException("Activity must implements fragment's callbacks !"); } callbacks = (Callbacks) activity; } /** 為Fragment加載布局時調用 **/ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { RadioGroup radioGroup = (RadioGroup) inflater.inflate(R.layout.fragment_bottom, container, false); //綁定監聽器 radioGroup.setOnCheckedChangeListener(changeListener); return radioGroup; } /**RadioGroup監聽器**/ private OnCheckedChangeListener changeListener = new OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group, int checkedId) { System.out.println(checkedId); callbacks.onItemSelected(checkedId); //調用接口中方法 } }; public interface Callbacks{ /**導航欄回調接口**/ public void onItemSelected(int item); } /**默認回調實現類的對象**/ private static Callbacks defaultCallbacks = new Callbacks() { @Override public void onItemSelected(int item) { //什么都不干 } }; /**Fragment和Activity解除關聯的時候調用**/ @Override public void onDetach() { super.onDetach(); callbacks = defaultCallbacks; } }
底部菜單布局fragment_bottom.xml
<?xml version="1.0" encoding="utf-8"?> <RadioGroup xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" > <RadioButton android:id="@+id/fragment_bottom_home" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" android:background="@drawable/fragment_bottom_selector" android:button="@null" android:drawableTop="@drawable/main_readiobutton_home" android:gravity="center" android:text="@string/home" android:textColor="@color/white" android:textSize="12sp" /> <View android:layout_width="1dp" android:layout_height="fill_parent" android:background="@color/white" /> <RadioButton android:id="@+id/fragment_bottom_order" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" android:background="@drawable/fragment_bottom_selector" android:button="@null" android:drawableTop="@drawable/main_readiobutton_order" android:gravity="center" android:text="@string/order" android:textColor="@color/white" android:textSize="12sp" /> <View android:layout_width="1dp" android:layout_height="fill_parent" android:background="@color/white" /> <RadioButton android:id="@+id/fragment_bottom_notice" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" android:background="@drawable/fragment_bottom_selector" android:button="@null" android:drawableTop="@drawable/main_readiobutton_notice" android:gravity="center" android:text="@string/notice" android:textColor="@color/white" android:textSize="12sp" /> <View android:layout_width="1dp" android:layout_height="fill_parent" android:background="@color/white" /> <RadioButton android:id="@+id/fragment_bottom_more" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" android:background="@drawable/fragment_bottom_selector" android:button="@null" android:drawablePadding="3dip" android:drawableTop="@drawable/main_readiobutton_more" android:gravity="center" android:text="@string/more" android:textColor="@color/white" android:textSize="12sp" /> </RadioGroup>
這里我們定義了一個框架類:GeneralFragment(所有的fragment界面都需繼承它)
package com.zhf.frameworkdemo02.fragments; import java.io.Serializable; import com.zhf.frameworkdemo02.R; import com.zhf.frameworkdemo02.view.OrderView; import com.zhf.frameworkdemo02.view.HomeView; import com.zhf.frameworkdemo02.view.MoreView; import com.zhf.frameworkdemo02.view.NoticeView; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; /** * 框架類,抽象公共方法 * @author ZHF * */ public class GeneralFragment extends Fragment implements Serializable{ /** * */ private static final long serialVersionUID = 1L; private int item; //用于區分底部菜單項 protected static View main_title_RelativeLayout; //標題欄 protected final static String key = "Bundle"; //跳轉值傳遞key的名稱 @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); if(getArguments() != null) { //根據接收子類傳來的arguments判斷item的哪一項 if(getArguments().containsKey(MainFragment.Item)) { item = getArguments().getInt(MainFragment.Item); } } } /**為Fragment加載布局時調用 **/ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_general, container, false); GeneralFragment fragment = null; switch(item) { case R.id.fragment_bottom_home: //初始化主頁 fragment = new HomeView(); break; case R.id.fragment_bottom_order: fragment = new OrderView(); //初始化訂單 break; case R.id.fragment_bottom_notice: fragment = new NoticeView(); //初始化公告 break; case R.id.fragment_bottom_more: fragment = new MoreView(); //初始化更多 break; default: break; } if(fragment != null) { //更換mainView中間的內容(home,msg,at,more) getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.general_fragment, fragment).commit(); } main_title_RelativeLayout = ((View) container.getParent()).findViewById(R.id.main_title_RelativeLayout); //將生成的view返回 return view; } /**設置標題**/ protected void setTitle(Object title) { if(main_title_RelativeLayout != null) { //標題欄中的文字 TextView mTvTitle = (TextView) main_title_RelativeLayout.findViewById(R.id.main_title_TextView); if(mTvTitle != null) { if(title instanceof Integer) { //整型 mTvTitle.setText((Integer)title); } else { //字符類型 mTvTitle.setText((CharSequence)title); } } } } /**頁面跳轉值傳遞**/ protected void setBundle(Object... objects) { Bundle arguments = new Bundle(); arguments.putSerializable(key, objects); GeneralFragment generalFragment = new GeneralFragment(); generalFragment.setArguments(arguments); } /**獲取所傳遞的值**/ protected Object[] getBundle() { if(getArguments() != null) { System.out.println("getBundle"); if(getArguments().containsKey(key)) { Object[] object = (Object[]) getArguments().getSerializable(key); return object; } } return null; } /**無參頁面跳轉**/ protected void toIntent(GeneralFragment generalFragment) { if(generalFragment != null) { getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.general_fragment, generalFragment).commit(); } } }
程序入口MainFragment:
package com.zhf.frameworkdemo02.fragments; import com.zhf.frameworkdemo02.R; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; /** *MainView * @author ZHF * */ public class MainFragment extends FragmentActivity implements BottomFragment.Callbacks { public final static String Item = "item"; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.main); //初始化默認調用接口中item選中方法 onItemSelected(R.id.fragment_bottom_home); } @Override public void onItemSelected(int item) { Bundle arguments = new Bundle(); arguments.putInt(Item, item); //將選中的底部radio的Id放進去 GeneralFragment generalFragment = new GeneralFragment(); generalFragment.setArguments(arguments); //設置參數值 //這里根據item的ID進行界面跳轉 FragmentManager fm = getSupportFragmentManager(); fm.beginTransaction().replace(R.id.main_detail_FrameLayout, generalFragment).commit(); } }
說明:這里我們的每個界面都將采用Fragment,故每個界面需重寫onCreateView()
package com.zhf.frameworkdemo02.view; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.zhf.frameworkdemo02.R; import com.zhf.frameworkdemo02.fragments.GeneralFragment; /** * 主頁面 * @author ZHF * */ public class HomeView extends GeneralFragment{ @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); super.setTitle("主頁"); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.home, container, false); } }
(其他三個略)
最終效果圖:
ok!大功告成!相當實用的!有興趣的可以學習一下!
×××:http://down.51cto.com/data/1009354
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。