티스토리 뷰
NavgationDrawer은 화면의 좌측 상단의 아이콘을 클릭했을 때, 바로가기 메뉴 등이 나타나도록 할 수 있는 화면이다.
프로젝트를 생성할 때, 해당 액티비티를 선택하여 생성하는 것 또한 가능하다.
프로젝트를 생성하고나서 activity_main.xml을 열어보면 아래와 같이 app_bar_main.xml 레이아웃 파일이 임포트되어 있고, 그 아래에 NavigationView 태그가 작성이 되어있다.
◎activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
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:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="@layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header_main"
app:menu="@menu/activity_main_drawer"/>
</androidx.drawerlayout.widget.DrawerLayout>
NavigationView객체를 보면, headerLayout과 menu 속성이 존재하는데 이는 각각 바로가기 메뉴 상단과 그 아래 표시될 메뉴를 나타낸다.
◎app_bar_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
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">
<com.google.android.material.appbar.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:theme="@style/Theme.Callenge.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/Theme.Callenge.PopupOverlay"/>
</com.google.android.material.appbar.AppBarLayout>
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
> </FrameLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
app_bar_main.xml 파일이 실질적인 메인화면 역할을 하는 레이아웃 파일이므로 여기에 FrameLayout을 하나 추가한다.
이제, NavigationView 에 정의된 헤더 속성과 메뉴 속성에 있는 nav_header_main.xml과 activity_main_drawer.xml를 확인해보면 다음과 같다.
◎nav_header_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"
android:layout_width="match_parent"
android:layout_height="@dimen/nav_header_height"
android:background="@drawable/side_nav_bar"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:theme="@style/ThemeOverlay.AppCompat.Dark"
android:orientation="vertical"
android:gravity="bottom">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing"
app:srcCompat="@mipmap/ic_launcher_round"
android:contentDescription="@string/nav_header_desc"
android:id="@+id/imageView"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing"
android:text="@string/nav_header_title"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/nav_header_subtitle"
android:id="@+id/textView"/>
</LinearLayout>
◎activity_main_drawer.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view">
<group android:checkableBehavior="single">
<item
android:id="@+id/nav_home"
android:icon="@drawable/ic_menu_camera"
android:title="@string/menu_home"/>
<item
android:id="@+id/nav_gallery"
android:icon="@drawable/ic_menu_gallery"
android:title="@string/menu_gallery"/>
<item
android:id="@+id/nav_slideshow"
android:icon="@drawable/ic_menu_slideshow"
android:title="@string/menu_slideshow"/>
</group>
</menu>
또한 menu에서 사용한 각 Fragment는 액티비티를 생성할 때 자동으로 생성되는데, 그 코드들을 다음과 같다.
◎fragment_home.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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=".ui.home.HomeFragment">
<TextView
android:id="@+id/text_home"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textAlignment="center"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
◎HomeFragment.class
package com.example.callenge.ui.home;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import com.example.callenge.R;
public class HomeFragment extends Fragment {
private HomeViewModel homeViewModel;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
homeViewModel =
new ViewModelProvider(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(getViewLifecycleOwner(), new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
textView.setText(s);
}
});
return root;
}
}
◎HomeViewModel.class
package com.example.callenge.ui.home;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
public class HomeViewModel extends ViewModel {
private MutableLiveData<String> mText;
public HomeViewModel() {
mText = new MutableLiveData<>();
mText.setValue("This is home fragment");
}
public LiveData<String> getText() {
return mText;
}
}
Fragment를 상속받고, inflate해주는 것 까지는 이해할 수 있지만 ViewModelProvider는 또 무엇이고 HomeViewModel은 또 왜 생성하는 지 의문이 많다.
이는 액티비티나 프래그먼트 간 데이터 전달을 좀 더 원할하게 해주는 역할이라고만 알아두고, 넘어가자. 다음 포스팅에서 좀 더 자세히 다루도록 하겠다.
이제 MainActivity.java를 다음과 같이 구성해주자.
◎MainActivity.java
package com.example.callenge;
import android.os.Binder;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.view.Menu;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.core.view.GravityCompat;
import androidx.fragment.app.Fragment;
import com.example.callenge.ui.gallery.GalleryFragment;
import com.example.callenge.ui.home.HomeFragment;
import com.example.callenge.ui.slideshow.SlideshowFragment;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.navigation.NavigationView;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import org.jetbrains.annotations.NotNull;
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener{
SlideshowFragment slideshowFragment;
HomeFragment homeFragment;
GalleryFragment galleryFragment;
DrawerLayout drawerLayout;
Toolbar toolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
drawerLayout = findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close
);
drawerLayout.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
galleryFragment = new GalleryFragment();
homeFragment = new HomeFragment();
slideshowFragment = new SlideshowFragment();
getSupportFragmentManager().beginTransaction().add(R.id.container, homeFragment).commit();
}
@Override
public boolean onNavigationItemSelected(@NonNull @NotNull MenuItem item) {
int id = item.getItemId();
if(id == R.id.nav_home) {
onFragmentSelected(0,null);
} else if(id == R.id.nav_gallery) {
onFragmentSelected(1,null);
} else if(id == R.id.nav_slideshow) {
onFragmentSelected(2,null);
}
drawerLayout.closeDrawer(GravityCompat.START);
return true;
}
public void onFragmentSelected(int position, Bundle bundle) {
Fragment curFragment = null;
if(position == 0) {
curFragment = homeFragment;
toolbar.setTitle("homeFragment");
} else if(position == 1) {
curFragment = galleryFragment;
toolbar.setTitle("galleryFragment");
} else if(position == 2) {
curFragment = slideshowFragment;
toolbar.setTitle("slideshowFragment");
}
getSupportFragmentManager().beginTransaction().replace(R.id.container, curFragment).commit();
}
}
'Mobile > Android' 카테고리의 다른 글
[Android] Service 1: Service 이해하기 (0) | 2022.03.29 |
---|---|
[Android] ViewModel (0) | 2022.03.27 |
[Android] View Pager2 (0) | 2022.03.25 |
[Android] Tab 2: 하단 Tab 구성 (0) | 2022.03.24 |
[Android] Tab 1: Tab 이해하기, 상단 Tab 구성 (0) | 2022.03.24 |
- 맛집
- Promise
- 인천 구월동 맛집
- redux-thunk
- await
- react-native
- javascript
- 파니노구스토
- AsyncStorage
- 이탈리안 레스토랑
- 인천 구월동 이탈리안 맛집
- Async
- redux
- 정보보안기사 #실기 #정리
- react
- Total
- Today
- Yesterday