在我们实际编写程序时,不必每一个activity都要从零开始,利用好系统自带的模板往往可以起到事半功倍的效果。下面我们就来看看如何使用Bottom Navigation Activity来完成简单的底部导航栏功能。先来看一下效果图吧:
创建activity
首先在创建面板,我们选择
然后next,finish就OK了。创建成功以后我们来运行一下,发现
已经基本实现了底部导航栏的功能了!但是还没有结束——我们还需要对导航栏进行修改定制,以符合我们自己的需要。
自定义底部导航
现在的底部导航只有三个选项,而且图标文字都是固定我。那么我们想增加导航或者改变图标文字应该怎么办呢?首先我们打开activity_main.xml文件,发现有这样一段代码
<android.support.design.widget.BottomNavigationView
android:id="@+id/nav_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/bottom_nav_menu" />
最后一行就是用来描述底部导航的。它指定了menu文件夹下的bottom_nav_menu文件。找到它看一下
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/navigation_home"
android:icon="@drawable/ic_home_black_24dp"
android:title="@string/title_home" />
<item
android:id="@+id/navigation_dashboard"
android:icon="@drawable/ic_dashboard_black_24dp"
android:title="@string/title_dashboard" />
<item
android:id="@+id/navigation_notifications"
android:icon="@drawable/ic_notifications_black_24dp"
android:title="@string/title_notifications" />
</menu>
这三个item对应的就是看到的三个图标。下面添加一行
<item android:id="@+id/test"
android:title="test"
android:icon="@drawable/compass"/>
title属性是点击后下面出现的文字,icon属性是图标这是下载地址。
我们再看已经出现了第四个图标(最多5个)。那么如何更改点击后的页面呢?
自定义切换页面(Fragment)
这里我们使用framgment来切换页面。
首先将activity_main.xml文件的textview改成
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</FrameLayout>
然后在layout文件夹下新建两个(如果要4个导航,那么新建4个文件,这里只创建两个测试用)layout文件
并在里面添加自己的布局。
然后打开mainactivity的java文件
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
return true;
case R.id.navigation_dashboard:
return true;
case R.id.navigation_notifications:
return true;
}
return false;
}
};
这一段代码就是底部导航切换的监听器(我把textview删掉了)。先加上我们自己的导航吧
case R.id.test:
return true;
然后新建两个java文件(对应两个layout,这里以一个为例)
public class content1 extends Fragment { //继承fragment
//创建视图
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate( R.layout.layout_1, container, false ); //要加载的layout文件
}
}
接下来就又是修改mainactivity了,我直接贴出代码
public class MainActivity extends AppCompatActivity {
private FragmentTransaction transaction;
private FragmentManager fragmentManager;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
fragmentManager = getSupportFragmentManager(); //使用fragmentmanager和transaction来实现切换效果
transaction = fragmentManager.beginTransaction();
switch (item.getItemId()) {
case R.id.navigation_home:
transaction.replace(R.id.content,new content1()); //对应的java class
transaction.commit(); //一定不要忘记commit,否则不会显示
return true;
case R.id.navigation_dashboard:
return true;
case R.id.navigation_notifications:
return true;
case R.id.test:
//一样的
transaction.replace(R.id.content,new content2());
transaction.commit();
return true;
}
return false;
}
};
// 设置默认进来是tab 显示的页面
private void setDefaultFragment(){
fragmentManager = getSupportFragmentManager();
transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.content,new content1());
transaction.commit();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_main );
setDefaultFragment(); //上面写的那个函数
BottomNavigationView navView = findViewById( R.id.nav_view );
navView.setOnNavigationItemSelectedListener( mOnNavigationItemSelectedListener );
}
}
到这里就结束啦!当然这只是最简单的使用,如果想要实现更复杂的功能还要同学们自己钻研啦!
更新
最新版的Android Studio(3.5)给出的模板和之前的不太一样,所以对文章进行一下更新。
还是先看一下效果,一个button和一个textview,点击button显示现在的时间:
文件结构
之前版本创建后只有一个java文件,现在是有多个文件:
dashboard,home,notifications这三个文件夹是对应的底部三个导航栏。每个文件夹下有两个文件,一个是用来承载控件的fragment,另一个是与之对应的viewModel。viewModel就是mvvm框架下的vm,关于mvvm框架同学们也可以研究一下,这里只简单说一下例子里面的HomeFragment和HomeViewModel。
首先这两个文件全是普通的java类。fragment用来显示ui界面,而viewmodel则是给ui界面提供数据,view里的每一个控件在viewmodel里都有一个对应的数据对象,如果要更新view上的ui界面,只需要更新viewmodel里与之对应的对象即可。
定制导航栏
对于导航栏的定制和之前大体相同,如果我们要新添一个自己的导航页可以这样操作:menu文件夹下的bottom_nav_menu.xml对应底部的导航图标,添加自己的item。
<item
android:id="@+id/navigation_my"
android:icon="@drawable/ic_notifications_black_24dp"
android:title="MyNavigation" />
然后在ui文件夹下新建一个文件夹命名为myNavagation,在里面new一个fragment->fragment with viewmodel
然后修改mainActivity部分代码如下:
BottomNavigationView navView = findViewById( R.id.nav_view );
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_my, R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications )
.build();
在navigation文件夹下的mobile_navigation.xml添加代码:
<fragment
android:id="@+id/navigation_my"
android:name="com.angel.hand.myapplication.ui.myNavigation.MyFragment"
android:label="myNavigation"
tools:layout="@layout/my_fragment"/>
这时候运行就能看到4个导航了。如果要修改页面的ui,就在对应的fragment_layout文件下修改。上述文件下的app:startDestination="@+id/navigation_home"
是设置默认启动页面的。
添加示例的功能
我们的示例主要是介绍这个模板而不是mvvm架构,所以代码比较简单。
HomeFragment代码:
public class HomeFragment extends Fragment {
private HomeViewModel homeViewModel;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
homeViewModel =
ViewModelProviders.of( this ).get( HomeViewModel.class );
View root = inflater.inflate( R.layout.fragment_home, container, false );
final TextView textView = root.findViewById( R.id.text_home );
homeViewModel.getText().observe( this, new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
textView.setText( s );
}
} );
final Button button = root.findViewById( R.id.btn );
button.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
textView.setText( homeViewModel.getDate() );
}
} );
return root;
}
}
HomeViewModel代码:
public class HomeViewModel extends ViewModel {
private MutableLiveData<String> mText;
private Date now;
public HomeViewModel() {
String time = "现在是什么时间?";
mText = new MutableLiveData<>();
mText.setValue( time );
}
public LiveData<String> getText() {
return mText;
}
public String getDate() {
now = new Date();
return now.toString();
}
}
好了,大致的内容就这些,有问题欢迎同学们讨论。