이번 포스팅에서는 Android로 BottomNavigation을 만드는 법에 대해 다루어보겠습니다 ‼️
보통 BottomNavigation을 쓰는 경우, 대다수는 MainActivity에 메뉴를 두고, 그 위에 여러 프래그먼트들이 들어갈 수 있는 FrameLayout
을 둡니다
메뉴 아이템이 눌릴 때마다 눌린 아이템의 id를 조회해 그에 맞는 프래그먼트를 노출시킵니다
위의 요소들을 MainActivity의 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_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.BottomNavigationView.Colored"
app:menu="@menu/bottom_nav_menu"/>
</LinearLayout>
⚠️ 여기서 FrameLayout의 weight를 설정해주어야 bottomNavigation이 아래로 향할 수 있습니다
style
: @style을 통해 앱 자체에 내장되어있는 스타일을 사용menu
리소스를 만들어 app:menu 속성에 추가 관련 설정은 아래 ⬇️navigation에 들어갈 메뉴들을 만들어줘야 합니다
res에 menu
라는 폴더를 새로 만들고 bottom.navigation.xml
을 새로 추가해주겠습니다
각 메뉴의 아이콘들은 drawable에 미리 추가해주었습니다
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/navigation_wordClock"
android:icon="@drawable/ic_home_black_24dp"
android:title="세계 시계" />
<item
android:id="@+id/navigation_alarm"
android:icon="@android:drawable/ic_lock_idle_alarm"
android:title="알람" />
<item
android:id="@+id/navigation_stopWatch"
android:icon="@drawable/ic_notifications_black_24dp"
android:title="스톱워치"/>
<item
android:id="@+id/navigation_timer"
android:icon="@android:drawable/ic_menu_recent_history"
android:title="타이머" />
</menu>
onCreate()
에서 MainActivity를 binding 해주고, bottomNavigation 변수를 id값을 통해 가져와 설정setOnItemSelectedListener
설정transferTo(Fragment fragment)
함수 생성public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//xml binding
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
//bottomNavigationView 가져오기
BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_navigation);
bottomNavigationView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == R.id.navigation_worldClock) {
transferTo(new WorldClockFragment());
return true;
} else if (item.getItemId() == R.id.navigation_alarm) {
transferTo(new AlarmFragment());
return true;
}
else if(item.getItemId() == R.id.navigation_stopWatch){
transferTo(new StopwatchFragment());
return true;
}
else if(item.getItemId() == R.id.navigation_timer){
transferTo(new TimerFragment());
return true;
}
return false;
}
});
}
//fragment가 눌렸을 때 해당 프래그먼트 노출시키기
void transferTo(Fragment fragment){
getSupportFragmentManager().beginTransaction()
.replace(R.id.main_content, fragment)
.commit();
}
}
Activity들은 activityManager에 의해 관리되는 것처럼, Fragment들도 fragmentManager에 의해 관리됩니다
🔎 Activity와 Fragment의 차이점 중 하나는 ActivityManager은 프레임워크에 존재하나, FragmentManager은 Activity에 존재하는 것이죠
아무튼 현재 코드는 액티비티에서 사용되니 바로 fragmentManager을 get해서 사용하면 되지만, fragment에서 fragmentManager을 사용할 때는 getActivity()
를 통해 액티비티를 먼저 얻은 후 getFragmentManager()
을 해야 합니다 ‼️
💡 transferTo()
함수에 대해 더 설명하자면,
해당 코드들은 프래그먼트 매니저가 관리하는 뷰들을 교체하는 코드입니다
교체의 종류에는 add
, replace
, remove
가 있고
⭐️ 이 세가지는 beginTransaction()
과 commit()
사이에서 이루어져야 합니다
함수에서 사용한 replace는 main_content
리소스에 fragment
로 뷰를 교체하겠다는 의미입니다
여기서 main_content
는 저희가 mainActivity의 xml에서 만든 frameLayout이며, fragment
는 인자로 들어온 fragment 객체를 뜻합니다
설정한대로 4개의 navigation item이 뜨고, 각 아이템을 눌렀을 때 설정한 프래그먼트가 layout에 뜨는 것을 볼 수 있습니다😊