android實(shí)現(xiàn)底部導(dǎo)航欄
底部導(dǎo)航欄我選擇用FragmentTabHost+Fragment來(lái)實(shí)現(xiàn),這個(gè)方法比較好用,代碼量也不多
首先是開(kāi)始的activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" >
<FrameLayout
android:id="@+id/main_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/main_tab"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" >
</FrameLayout>
<view
android:id="@+id/main_tab"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
class="android.support.v4.app.FragmentTabHost" />
</RelativeLayout>
也可以直接在xml文件里面寫(xiě)
<android.support.v4.view.FragmentTabHost > </android.support.v4.view.FragmentTabHost>
這xml文件就一個(gè)view加一個(gè)tab view用來(lái)顯示碎片,tab用來(lái)放置底部按鈕的數(shù)量
再來(lái)是tab_foot.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#F6F6F6" android:gravity="center" android:orientation="vertical" > <ImageView android:id="@+id/foot_iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/home1" /> <TextView android:id="@+id/foot_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="3dp" android:text="首頁(yè)" android:textColor="@color/tab_color" /> </LinearLayout>
這是每個(gè)底部按鈕的布局設(shè)置的xml文件
再來(lái)是MainActivity的代碼
package com.gjn.mynavigation;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTabHost;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.widget.ImageView;
import android.widget.TabWidget;
import android.widget.TextView;
import android.widget.TabHost.OnTabChangeListener;
import android.widget.TabHost.TabSpec;
public class MainActivity extends FragmentActivity implements OnTabChangeListener {
private FragmentTabHost mTabHost;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
//初始化FragmentTabHost
initHost();
//初始化底部導(dǎo)航欄
initTab();
//默認(rèn)選中
mTabHost.onTabChanged(TabDb.getTabsTxt()[0]);
}
private void initTab() {
String[] tabs = TabDb.getTabsTxt();
for (int i = 0; i < tabs.length; i++) {
//新建TabSpec
TabSpec tabSpec = mTabHost.newTabSpec(TabDb.getTabsTxt()[i]);
//設(shè)置view
View view = LayoutInflater.from(this).inflate(R.layout.tabs_foot, null);
((TextView) view.findViewById(R.id.foot_tv)).setText(TabDb.getTabsTxt()[i]);
((ImageView) view.findViewById(R.id.foot_iv)).setImageResource(TabDb.getTabsImg()[i]);
tabSpec.setIndicator(view);
//加入TabSpec
mTabHost.addTab(tabSpec,TabDb.getFramgent()[i],null);
}
}
/***
* 初始化Host
*/
private void initHost() {
mTabHost = (FragmentTabHost) findViewById(R.id.main_tab);
//調(diào)用setup方法 設(shè)置view
mTabHost.setup(this, getSupportFragmentManager(),R.id.main_view);
//去除分割線(xiàn)
mTabHost.getTabWidget().setDividerDrawable(null);
//監(jiān)聽(tīng)事件
mTabHost.setOnTabChangedListener(this);
}
@Override
public void onTabChanged(String arg0) {
//從分割線(xiàn)中獲得多少個(gè)切換界面
TabWidget tabw = mTabHost.getTabWidget();
for (int i = 0; i < tabw.getChildCount(); i++) {
View v = tabw.getChildAt(i);
TextView tv = (TextView) v.findViewById(R.id.foot_tv);
ImageView iv = (ImageView) v.findViewById(R.id.foot_iv);
//修改當(dāng)前的界面按鈕顏色圖片
if (i == mTabHost.getCurrentTab()) {
tv.setTextColor(getResources().getColor(R.color.tab_light_color));
iv.setImageResource(TabDb.getTabsImgLight()[i]);
}else{
tv.setTextColor(getResources().getColor(R.color.tab_color));
iv.setImageResource(TabDb.getTabsImg()[i]);
}
}
}
}
其中TabDb類(lèi)是用來(lái)設(shè)置導(dǎo)航欄的數(shù)據(jù)和圖片切換時(shí)候的資源
以下是TabDb類(lèi)
package com.gjn.mynavigation;
public class TabDb {
/***
* 獲得底部所有項(xiàng)
*/
public static String[] getTabsTxt() {
String[] tabs = {"首頁(yè)","交易","地點(diǎn)","我的"};
return tabs;
}
/***
* 獲得所有碎片
*/
public static Class[] getFramgent(){
Class[] cls = {OneFm.class,TwoFm.class,ThreeFm.class,FourFm.class};
return cls ;
}
/***
* 獲得所有點(diǎn)擊前的圖片
*/
public static int[] getTabsImg(){
int[] img = {R.drawable.home1,R.drawable.glod1,R.drawable.xc1,R.drawable.user1};
return img ;
}
/***
* 獲得所有點(diǎn)擊后的圖片
*/
public static int[] getTabsImgLight(){
int[] img = {R.drawable.home2,R.drawable.glod2,R.drawable.xc2,R.drawable.user2};
return img ;
}
}
到此,底部導(dǎo)航欄就算是完全實(shí)現(xiàn)了。
現(xiàn)在來(lái)實(shí)現(xiàn)頂部導(dǎo)航欄,看了許多最后使用了RadioGroup+ViewPager來(lái)實(shí)現(xiàn)
首先是為第一個(gè)碎片設(shè)計(jì)一個(gè)xml布局:fm_one.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <HorizontalScrollView android:id="@+id/one_hv" android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollbars="none" > <RadioGroup android:id="@+id/one_rg" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > </RadioGroup> </HorizontalScrollView> <view android:id="@+id/one_view" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" class="android.support.v4.view.ViewPager" /> </LinearLayout>
設(shè)置頂部導(dǎo)航欄和顯示view
之后是導(dǎo)航欄的每個(gè)項(xiàng)的布局
tab_rb.xml
<?xml version="1.0" encoding="utf-8"?> <RadioButton xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/tab_rb_selector" android:button="@null" android:paddingBottom="10dp" android:paddingLeft="15dp" android:paddingRight="15dp" android:paddingTop="10dp" android:text="今日" > </RadioButton>
其中設(shè)置selector文件來(lái)控制點(diǎn)擊和未點(diǎn)擊的狀態(tài)
tab_rb_selector.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" > <!-- 點(diǎn)擊 --> <item android:state_checked="true"> <layer-list > <item > <shape android:shape="rectangle"> <stroke android:width="5dp" android:color="@color/tab_light_color"/> </shape> </item> <item android:bottom="5dp"> <shape android:shape="rectangle"> <solid android:color="#fff"/> </shape> </item> </layer-list> </item> <!-- 默認(rèn) --> <item > <shape > <solid android:color="#fafafa"/> </shape> </item> </selector>
設(shè)置了點(diǎn)擊和默認(rèn)的時(shí)候的顯示狀態(tài)
最后來(lái)實(shí)現(xiàn)OneFm類(lèi)
package com.gjn.mynavigation;
import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.LayoutParams;
import android.widget.RadioGroup.OnCheckedChangeListener;
public class OneFm extends Fragment implements OnPageChangeListener {
private View view;
private RadioGroup rg_;
private ViewPager vp_;
private HorizontalScrollView hv_;
private List<Fragment> newsList = new ArrayList<Fragment>();
private OneFmAdapter adapter;
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
if (view == null) {
//初始化view
view = inflater.inflate(R.layout.fm_one, container,false);
rg_ = (RadioGroup) view.findViewById(R.id.one_rg);
vp_ = (ViewPager) view.findViewById(R.id.one_view);
hv_ = (HorizontalScrollView) view.findViewById(R.id.one_hv);
//設(shè)置RadioGroup點(diǎn)擊事件
rg_.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int id) {
vp_.setCurrentItem(id);
}
}
//初始化頂部導(dǎo)航欄
initTab(inflater);
//初始化viewpager
initView();
}
/**
* 底部導(dǎo)航欄切換后 由于沒(méi)有銷(xiāo)毀頂部設(shè)置導(dǎo)致如果沒(méi)有重新設(shè)置view
* 導(dǎo)致底部切換后切回頂部頁(yè)面數(shù)據(jù)會(huì)消失等bug
* 以下設(shè)置每次重新創(chuàng)建view即可
*/
ViewGroup parent = (ViewGroup) view.getParent();
if (parent != null) {
parent.removeView(view);
}
return view;
}
/***
* 初始化viewpager
*/
private void initView() {
List<HTab> hTabs = HTabDb.getSelected();
for (int i = 0; i < hTabs.size(); i++) {
OneFm1 fm1 = new OneFm1();
Bundle bundle = new Bundle();
bundle.putString("name", hTabs.get(i).getName());
fm1.setArguments(bundle);
newsList.add(fm1);
}
//設(shè)置viewpager適配器
adapter = new OneFmAdapter(getActivity().getSupportFragmentManager(),newsList);
vp_.setAdapter(adapter);
//兩個(gè)viewpager切換不重新加載
vp_.setOffscreenPageLimit(2);
//設(shè)置默認(rèn)
vp_.setCurrentItem(0);
//設(shè)置viewpager監(jiān)聽(tīng)事件
vp_.setOnPageChangeListener(this);
}
/***
* 初始化頭部導(dǎo)航欄
* @param inflater
*/
private void initTab(LayoutInflater inflater) {
List<HTab> hTabs = HTabDb.getSelected();
for (int i = 0; i < hTabs.size(); i++) {
//設(shè)置頭部項(xiàng)布局初始化數(shù)據(jù)
RadioButton rbButton = (RadioButton) inflater.inflate(R.layout.tab_rb, null);
rbButton.setId(i);
rbButton.setText(hTabs.get(i).getName());
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
//加入RadioGroup
rg_.addView(rbButton,params);
}
//默認(rèn)點(diǎn)擊
rg_.check(0);
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageSelected(int id) {
setTab(id);
}
/***
* 頁(yè)面跳轉(zhuǎn)切換頭部偏移設(shè)置
* @param id
*/
private void setTab(int id) {
RadioButton rbButton = (RadioButton) rg_.getChildAt(id);
//設(shè)置標(biāo)題被點(diǎn)擊
rbButton.setChecked(true);
//偏移設(shè)置
int left = rbButton.getLeft();
int width = rbButton.getMeasuredWidth();
DisplayMetrics metrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
int screenWidth = metrics.widthPixels;
//移動(dòng)距離= 左邊的位置 + button寬度的一半 - 屏幕寬度的一半
int len = left + width / 2 - screenWidth / 2;
//移動(dòng)
hv_.smoothScrollTo(len, 0);
}
}
其中有兩個(gè)數(shù)據(jù)類(lèi)和一個(gè)碎片類(lèi)
數(shù)據(jù)類(lèi)
HTab.java
package com.gjn.mynavigation;
/***
* 頭部Tab屬性
*
*/
public class HTab {
private String name;
public HTab(String name) {
super();
this.setName(name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
HTabDb.java
package com.gjn.mynavigation;
import java.util.ArrayList;
import java.util.List;
public class HTabDb {
private static final List<HTab> Selected = new ArrayList<HTab>();
static{
Selected.add(new HTab("今日"));
Selected.add(new HTab("頭條"));
Selected.add(new HTab("娛樂(lè)"));
Selected.add(new HTab("財(cái)經(jīng)"));
Selected.add(new HTab("軍事"));
Selected.add(new HTab("科技"));
Selected.add(new HTab("時(shí)尚"));
Selected.add(new HTab("體育"));
}
/***
* 獲得頭部tab的所有項(xiàng)
*/
public static List<HTab> getSelected() {
return Selected;
}
}
碎片類(lèi)
OneFm1.java
package com.gjn.mynavigation;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class OneFm1 extends Fragment {
private String name;
@Override
public void setArguments(Bundle args) {
name = args.getString("name");
}
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment, container,false);
((TextView) view.findViewById(R.id.fm_text)).setText(name);
return view;
}
}
這樣就把頂部的導(dǎo)航欄加入到了第一個(gè)fragment里面并且實(shí)現(xiàn)了切換功能
最后把fragment.xml貼下,就是每個(gè)碎片最默認(rèn)的顯示頁(yè)面
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" > <TextView android:id="@+id/fm_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Large Text" android:textAppearance="?android:attr/textAppearanceLarge" /> </LinearLayout>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android實(shí)現(xiàn)底部導(dǎo)航欄功能
- Android程序開(kāi)發(fā)之Fragment實(shí)現(xiàn)底部導(dǎo)航欄實(shí)例代碼
- Android實(shí)現(xiàn)底部導(dǎo)航欄功能(選項(xiàng)卡)
- Android中TabLayout+ViewPager 簡(jiǎn)單實(shí)現(xiàn)app底部Tab導(dǎo)航欄
- Android design包自定義tablayout的底部導(dǎo)航欄的實(shí)現(xiàn)方法
- android中Fragment+RadioButton實(shí)現(xiàn)底部導(dǎo)航欄
- Android實(shí)現(xiàn)簡(jiǎn)單底部導(dǎo)航欄 Android仿微信滑動(dòng)切換效果
- 性能分析:指如何快速定位SQL問(wèn)題
- Android用Scroller實(shí)現(xiàn)一個(gè)可向上滑動(dòng)的底部導(dǎo)航欄
- 使用RadioButton+Fragment實(shí)現(xiàn)底部導(dǎo)航欄效果
相關(guān)文章
詳解Android studio如何導(dǎo)入jar包方法
這篇內(nèi)容主要給大家詳細(xì)說(shuō)明了如何導(dǎo)入jar包,以及Android studio遇到的各種問(wèn)題和解決辦法。2017-12-12
詳談Android中onTouch與onClick事件的關(guān)系(必看)
下面小編就為大家?guī)?lái)一篇詳談Android中onTouch與onClick事件的關(guān)系(必看)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-03-03
Kotlin構(gòu)造函數(shù)與成員變量和init代碼塊執(zhí)行順序詳細(xì)講解
這篇文章主要介紹了Kotlin構(gòu)造函數(shù)與成員變量和init代碼塊執(zhí)行順序,kotlin里面的構(gòu)造函數(shù)分為主構(gòu)造函數(shù)和次構(gòu)造函數(shù)。主構(gòu)造函數(shù)只能有一個(gè),次構(gòu)造函數(shù)個(gè)數(shù)不限制,可以有一個(gè)或者多個(gè)2022-11-11
為Android Studio編寫(xiě)自定義Gradle插件的教程
這篇文章主要介紹了為Android Studio編寫(xiě)自定義Gradle插件的教程,Android Studio現(xiàn)在基本上已經(jīng)成為了安卓開(kāi)發(fā)的標(biāo)配IDE,友可以參考下2016-02-02
Android 進(jìn)程間通信實(shí)現(xiàn)原理分析
只有你允許客戶(hù)端從不同的應(yīng)用程序?yàn)榱诉M(jìn)程間的通信而去訪(fǎng)問(wèn)你的service,以及想在你的service處理多線(xiàn)程,下面為大家詳細(xì)介紹下2013-06-06
Android利用ContentProvider初始化組件的踩坑記錄
做Android SDK開(kāi)發(fā)的時(shí)候,一般我們會(huì)將初始化的方法封裝,然后讓調(diào)用SDK的開(kāi)發(fā)者在Application的onCreate方法中進(jìn)行初始化,下面這篇文章主要給大家介紹了關(guān)于Android利用ContentProvider初始化組件的踩坑記錄,需要的朋友可以參考下2022-04-04
Android自定義通用標(biāo)題欄CustomTitleBar
這篇文章主要為大家詳細(xì)介紹了Android自定義通用標(biāo)題欄CustomTitleBar,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11
Android Studio 代理配置指南(小結(jié))
這篇文章主要介紹了Android Studio 代理配置指南(小結(jié)),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-01-01

