Android implements the main interface of the bottom navigation bar

In mainstream apps, the main interface of the application is a navigation bar with multiple tabs at the bottom. Click to switch to the corresponding interface, as shown in the figure:

Next, the implementation process will be described.

1. The first is the analysis interface. On the bottom navigation bar, we can use a linear layout with full screen width, several labels wrapped in textview and horizontal orientation. At the top is a FrameLayout that takes up the remaining space.

activity_ main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 tools:context=".MainActivity"
 android:orientation="vertical">
 <FrameLayout
 android:id="@+id/main_layout"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:layout_weight="1"/>
 <View
 android:layout_width="match_parent"
 android:layout_height="1px"
 android:background="@color/colorPrimaryDark"
 />
 <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:orientation="horizontal">
 <TextView
  android:id="@+id/main_home"
  android:layout_width="wrap_content"
  android:layout_weight="1"
  android:layout_height="wrap_content"
  android:gravity="center"
  android:padding="20dp"
  android:text="首页"
  />
 <View
  android:layout_width="1px"
  android:layout_height="match_parent"
  android:background="@color/colorPrimaryDark"
  />
 <TextView
  android:id="@+id/main_game"
  android:layout_width="wrap_content"
  android:layout_weight="1"
  android:layout_height="wrap_content"
  android:gravity="center"
  android:padding="20dp"
  android:text="游戏"
  />
 <View
  android:layout_width="1px"
  android:layout_height="match_parent"
  android:background="@color/colorPrimaryDark"
  />
 <TextView
  android:id="@+id/main_video"
  android:layout_width="wrap_content"
  android:layout_weight="1"
  android:layout_height="wrap_content"
  android:gravity="center"
  android:padding="20dp"
  android:text="视频"
  />
 <View
  android:layout_width="1px"
  android:layout_height="match_parent"
  android:background="@color/colorPrimaryDark"
  />
 <TextView
  android:id="@+id/main_mine"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_weight="1"
  android:gravity="center"
  android:padding="20dp"
  android:text="我的"
  />
 </LinearLayout>
</LinearLayout>

2. Four tags correspond to four fragments. We can create four fragments and put a textview in the layout for differentiation.

private HomeFragment homeFragment;
private GameFragment gameFragment;
private VideoFragment videoFragment;
private mineFragment mineFragment;

3. Open mainactivity and initialize the control first

private void initView() {
 home= findViewById(R.id.main_home);
 game= findViewById(R.id.main_game);
 video= findViewById(R.id.main_video);
 mine= findViewById(R.id.main_mine);
 layout= findViewById(R.id.main_layout);

 home.setOnClickListener(this);
 game.setOnClickListener(this);
 video.setOnClickListener(this);
 mine.setOnClickListener(this);
}

Onclick click events are processed later

3. Initialize four fragments

Our original intention is that after the fragment is loaded once, repeated clicks or switching back will not load again to consume resources. The common processing methods here include lazy loading of viewpager and hide and show of fragment. Here we explain the implementation of the latter.

private void initFragment() {
 FragmentTransaction transaction= getSupportFragmentManager().beginTransaction();
 if (homeFragment!= null&& homeFragment.isAdded()){
 transaction.remove(homeFragment);
 }
 if (gameFragment!= null&& gameFragment.isAdded()){
 transaction.remove(gameFragment);
 }
 if (videoFragment!= null&& videoFragment.isAdded()){
 transaction.remove(videoFragment);
 }
 if (mineFragment!= null&& mineFragment.isAdded()){
 transaction.remove(mineFragment);
 }
 transaction.commitAllowingStateLoss();
 homeFragment= null;
 gameFragment= null;
 videoFragment= null;
 mineFragment= null;
 home.performClick();
}

Let's analyze the code line by line

Start a transaction first

FragmentTransaction transaction= getSupportFragmentManager().beginTransaction();

Non null processing of fragment

if (homeFragment!= null&& homeFragment.isAdded()){
 transaction.remove(homeFragment);
}
if (gameFragment!= null&& gameFragment.isAdded()){
 transaction.remove(gameFragment);
}
if (videoFragment!= null&& videoFragment.isAdded()){
 transaction.remove(videoFragment);
}
if (mineFragment!= null&& mineFragment.isAdded()){
 transaction.remove(mineFragment);
}
transaction.commitAllowingStateLoss();

Set all fragments to null, and the click event of homefragment will be automatically executed, that is, homefragment will be displayed by default

homeFragment= null;
gameFragment= null;
videoFragment= null;
mineFragment= null;
home.performClick();

4. Back to the click events of the four bottom tabs, we execute the custom switchcontent method and pass in the view of the currently clicked tab as a parameter

@Override
public void onClick(View view) {
 switch (view.getId()){
 case R.id.main_home:
  switchContent(home);
  break;
 case R.id.main_game:
  switchContent(game);
  break;
 case R.id.main_video:
  switchContent(video);
  break;
 case R.id.main_mine:
  switchContent(mine);
  break;
 }
}

5. Locate the switchcontent method

Create a new fragment object. When a tag is clicked, if the current fragment object is empty, an object instance corresponding to the fragment will be generated

public void switchContent(View view){
 Fragment fragment;
 if (view== home){
 if (homeFragment== null){
  homeFragment= new HomeFragment();
 }
 fragment= homeFragment;
 }else if (view== game){
 if (gameFragment== null){
  gameFragment= new GameFragment();
 }
 fragment= gameFragment;
 }else if (view== video){
 if (videoFragment== null){
  videoFragment= new VideoFragment();
 }
 fragment= videoFragment;
 }else if (view== mine){
 if (mineFragment== null){
  mineFragment= new mineFragment();
 }
 fragment= mineFragment;
 }else {
 return;
 }

After generating the object, we can add and display the fragment.

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (mContent == null) {
 transaction.add(layout.getId(),fragment).commit();
 mContent = fragment;
}
if (mContent != fragment) {
 if (!fragment.isAdded()) {
 transaction.hide(mContent).add(layout.getId(),fragment).commitAllowingStateLoss();
 } else {
 transaction.hide(mContent).show(fragment).commitAllowingStateLoss();
 }
 mContent = fragment;
}
home.setSelected(false);
home.setSelected(false);
home.setSelected(false);
home.setSelected(false);
view.setSelected(true);

When analyzing this code, we mainly compare the current fragment mcontent with the previous fragment, so as to judge whether the navigation bar at the bottom has been clicked for switching. First, when the application is opened, because we called the first tag automatic click method earlier.

home.performClick();

Look at the process, because mcontent is still null at this time, so go to this code

if (mContent == null) {
 transaction.add(layout.getId(),fragment).commit();
 mContent = fragment;
}

At this time, the fragment is the homefragment object. The page will display the homefragment and assign the object to mcontent.

At this point, the life cycle of homefragment is as follows. Everything is normal from attach() to onresume().

Next, click the second tab, where fragment is gamefragment and mcontent is homefragment. The two are different. Take this method.

if (mContent != fragment) {
 if (!fragment.isAdded()) {
 transaction.hide(mContent).add(layout.getId(),fragment).commitAllowingStateLoss();
 } else {
 transaction.hide(mContent).show(fragment).commitAllowingStateLoss();
 }
 mContent = fragment;
}

Analyze the code. The gamefragment has not been loaded yet, so go first

transaction.hide(mContent).add(layout.getId(),fragment).commitAllowingStateLoss();

That is, hide the mcontent, that is, the homefragment, and display it when the gamefragment is loaded.

At this time, looking at the life cycle of gamefragment, everything is normal.

At this time, we click back to homefragment. At this time, fragment is homefragment, mcontent is gamefragment, and homefragment has been added, so we go

transaction.hide(mContent).show(fragment).commitAllowingStateLoss();

This statement refers to hiding the fragments without loading the fragments already loaded by add. You can directly show them. The commitallowingstateloss method is similar to the commit method, which is more suitable for submitting work under frequent page switching to avoid crash.

At the same time, open the log and find that the homefragment has not been destroyed and overloaded, so we don't want to switch frequent loading.

This is all done, and the demo is attached!

Resource download

The above is the whole content of this article. I hope it will help you in your study, and I hope you will support us a lot.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>