[Android Studio]Fragment + NavigationView사용하기

|

NavigationView을 사용할 때, 앱이 구동되는 내내 어디든지 혹은 두 곳(Activity) 이상에서 NavigationView를 사용(보이게)하려면 

크게 두 가지 방법이 있을 것이다.
하나는 최상단의 Layout을 L, NavigationView를 N, Fragment를 F, 아무것도 아닌 것을 X라고 했을 때에,
LFNL 처럼 되어서 LXNL이란 형식은 유지된 채, F부분만 다른 걸로 계속 replace를 해주는 방법.
이렇게 하면, 중복되는 부분(NavigationView)은 계속 재활용할 수 있게 된다.

다른 하나는 매 Layout마다 NavigationView를 만들어 작성하는 것이다.
이렇게 되면, NavigationView를 Layout 마다 만들어야 하므로 여러개 사용이 된다.
activity_main: LXNL
activity_setting: LXNL
...
와 같은 형태로 말이다.
이렇게 되면 XML에서 뿐만 아니라 Java에서도 코드가 계속 중복되게 된다.

결론적으로 redundant를 피하므로 전자가 낫다.

즉,
하나의 Layout에서 Fragment란 View를 사용하여 그 부분만 바뀌게끔 하면 된다.
(단, NavigationView이 접혔을 때에 기본으로 보여지는 각각에 화면에 맞는 여러개의 Layout은 원래 필요하다.
파일명은 fragment_xxx식으로 하나, 내용은 LFNL에서, F부분만 여러 파일로 나누므로 NavigationView나 기타 Fragment가 아닌 부분을 작성하지 않으므로 activity_xxx와 좀 살짝 다르다.)

MainActivity.java와 AFragment, BFragment가 있다고 하자.
AB화면에서도 NavigationView를 보여주고 싶으면 이 두 Fragment를 하나의 Activity로 묶어주고, 그 Activity가 NavigationView를 가지고 있는 상태에서 AFragment, BFragment로만 Fragment부분을 replace해주면 된다.

*Fragment는 android.support.v4.app.Fragment이다.

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener{ // nav ImageView navImage; TextView navUserId; TextView navEmail; View navHeader; NavigationView navigationView; // fragment FrameLayout contentFL; Fragment contentFragment = null; Class fragmentClass = SearchFragment.class; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, drawer, null, R.string.navigation_drawer_open, R.string.navigation_drawer_close); drawer.addDrawerListener(toggle); toggle.syncState(); navigationView = (NavigationView) findViewById(R.id.nav_view); navigationView.setNavigationItemSelectedListener(this); navHeader = navigationView.getHeaderView(0); contentFL = findViewById(R.id.content_framlayout_appbar_navigation); FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.replace(R.id.content_framlayout_appbar_navigation, new SearchFragment()).commit(); } // Navigation @Override public void onBackPressed() { DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); if (drawer.isDrawerOpen(GravityCompat.START)) { drawer.closeDrawer(GravityCompat.START); } else { super.onBackPressed(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } @SuppressWarnings("StatementWithEmptyBody") @Override public boolean onNavigationItemSelected(MenuItem item) { // Handle navigation view item clicks here. int id = item.getItemId(); switch (id) { case R.id.nav_a: Toast.makeText(this, "Message Menu Clicked!"+item.getTitle(), Toast.LENGTH_SHORT).show(); fragmentClass = AFragment.class; break; case R.id.nav_b: Toast.makeText(this, "Message Menu Clicked!"+item.getTitle(), Toast.LENGTH_SHORT).show(); fragmentClass = BFragment.class; } }
public class AFragment extends Fragment { View view; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { view = inflater.inflate(R.layout.fragment_a, null); return view; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { // TODO ex. TextView tv = view.findViewById(R.id.xxx); super.onActivityCreated(savedInstanceState); } }
public class BFragment extends Fragment { View view; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { view = inflater.inflate(R.layout.fragment_b, null); return view; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { // TODO ex. TextView tv = view.findViewById(R.id.xxx); super.onActivityCreated(savedInstanceState); } }

이런식으로 해주면 되겠다.
*Fragment는 onCreate, onCreateView, onActivityCreated 이렇게 기본적으로 세가지 중요한 메소드를 오버라이드해서 사용하게 된다.

MainActivity는 다음과 같이 하면 된다.

<?xml version="1.0" encoding="utf-8"?> <android.support.v4.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"> <FrameLayout android:id="@+id/content_framlayout_appbar_navigation" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" > </FrameLayout> <android.support.design.widget.NavigationView android:id="@+id/nav_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" android:fitsSystemWindows="true" android:background="@color/themeColor" app:headerLayout="@layout/nav_header" app:menu="@menu/nav_menu" /> </android.support.v4.widget.DrawerLayout>

Fragment의 레이아웃은

<FrameLayout 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="org.koreanlab.fragment.SettingFragment"> <!-- TODO: Update blank fragment layout --> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:text="IamSetting" /> </FrameLayout>

이런식으로 내부에 원하는 데코레이션대로 만들면 된다.


And