로그인 바로가기 하위 메뉴 바로가기 본문 바로가기
난이도
심화

안드로이드 앱 프로그래밍

임시 이미지 정재곤
http://www.boostcourse.org/mo316/notice/2523
좋아요 1436 수강생 20099
아래의 글은 BOOSTER 서포터즈로 활동했던 케니(kart***)님이
작성한 부스트코스 후기입니다.
여러분들의 성원에 더 노력하는 부스트코스가 되겠습니다.
감사합니다.
******************************************
1)링크: https://blog.naver.com/kartmon/221609109500
2)작성날짜: 19/08/07
 
<본문내용>

4. 탭 사용하기

액션바에 탭을 추가하여서 여러개의 뷰를 한 화면에서 보여줄 수 있다.

design 외부 라이브러리 설치

메인 레이아웃은 다음과 같은 식으로 구성된다.

<CoordinatorLayout> <AppBarLayout> <Toolbar> </Toolbar> <TabLayout> </TabLayout> </AppBarLayout> <FrameLayout> </FrameLayout> </CoordinatorLayout>
<!--화면 전체를 채워준다.(자동으로 겹침 문제를 해결해준다.)--><androidx.coordinatorlayout.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent"><!--액션바 생성--><com.google.android.material.appbar.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"><!--툴바 생성--><androidx.appcompat.widget.Toolbar android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorPrimaryDark" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" android:elevation="1dp" android:id="@+id/toolbar"></androidx.appcompat.widget.Toolbar><com.google.android.material.tabs.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" android:elevation="1dp" android:background="@android:color/background_light" app:tabMode="fixed" app:tabGravity="fill" app:tabTextColor="@color/colorPrimary" app:tabSelectedTextColor="@color/colorAccent"></com.google.android.material.tabs.TabLayout></com.google.android.material.appbar.AppBarLayout><FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" android:id="@+id/container"></FrameLayout></androidx.coordinatorlayout.widget.CoordinatorLayout>

메인액티비티.java

public class MainActivity extends AppCompatActivity { Fragement1 fragement1; Fragement2 fragement2; Fragement3 fragement3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //액션바에 툴바 추가 androidx.appcompat.widget.Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); //프래그먼트 선언 fragement1 = new Fragement1(); fragement2 = new Fragement2(); fragement3 = new Fragement3(); getSupportFragmentManager().beginTransaction() .add(R.id.container,fragement1).commit(); //탭 레이아웃 호출 후 탭 추가 TabLayout tabs = (TabLayout) findViewById(R.id.tabs); tabs.addTab(tabs.newTab().setText("친구")); tabs.addTab(tabs.newTab().setText("일대일채팅")); tabs.addTab(tabs.newTab().setText("기타")); //각 탭을 누를 때 메소드 호출 tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { //몇번째 탭을 선택했는지 가져옴 int position = tab.getPosition(); //탭을 선택 한것에 따라 프래그먼트를 바꾼다. Fragment selected = null; if(position == 0){ selected = fragement1; } else if(position == 1){ selected = fragement2; } else if(position == 2){ selected = fragement3; } getSupportFragmentManager().beginTransaction() .replace(R.id.container,selected).commit(); } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { } }); } }

프래그먼트1.java

public class Fragement1 extends Fragment { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment1,container,false); return rootView; } }

프래그먼트2.java

public class Fragement2 extends Fragment { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment2,container,false); return rootView; } }

프래그먼트3.java

public class Fragement3 extends Fragment { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment3,container,false); return rootView; } }

출력 결과

1) 탭 만들기

생각해보기

탭 버튼에 아이콘 이미지가 보이게 하려면 어떻게 해야 할까요?

- Tab.setTabIconTintResource()메소드로 추가 가능할 것 같습니다.

첫 번째 탭 안에 있는 버튼을 눌렀을 때 두 번째 탭 화면이 보이도록 하고 싶다면 어떻게 하면 될까요?

- 첫번째 프래그먼트에서 버튼을 누르면 메인 액티비티에서 두번째 프래그먼트를 호출하게 하면 될것 같습니다. 라고 처음에 생각했지만 그렇게 되면 탭은 전환이 되지 않기 때문에 onTabListener를 통해서 전환 해줘야 할 것 같습니다.

5. 뷰페이저 사용하기

1) 뷰페이저(ViewPager) 만들기

좌우로 스크롤을 하면 화면을 넘길 수 있는 기능을 뷰 페이저라고 한다.

뷰페이저 안에는 여러개의 화면이 들어갈 수 있다. 이때 여러개의 프래그 먼트를 사용하게 된다.

리스트뷰와 마찬가지로 여러개 중에 하나를 선택하기 때문에 어댑터 패턴을 사용하게 된다.

생각해보기

뷰 페이저의 각 아이템에 보이는 프래그먼트가 동일한 레이아웃을 가지고 있다면 프래그먼트를 하나만 정의할 수도 있을까요?

- 네 동일한 프래그먼트를 어뎁터에 추가해서 사용 가능할 것 같습니다.

뷰페이저 외에 좌우 스크롤을 이용해 화면을 넘겨볼 수 있는 다른 방법이 있을까요?

- horizontal 뷰로 스크롤을 만들어 사용할 수 있다고 생각합니다.

2) 타이틀스트립 사용하기

뷰페이저를 사용할때 뷰가 몇개인지 모르기 때문에 타이틀 스트립을 통해서 확인이 가능하다.

메인액티비티.java

public class MainActivity extends AppCompatActivity { ViewPager pager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); pager = (ViewPager) findViewById(R.id.pager); //화면상에 보여주는 아이템의 개수를 제한 pager.setOffscreenPageLimit(3); //어댑터 생성 MoviePagerAdapter adapter = new MoviePagerAdapter(getSupportFragmentManager()); Fragment1 fragment1 = new Fragment1(); adapter.addItem(fragment1); Fragment2 fragment2 = new Fragment2(); adapter.addItem(fragment2); Fragment3 fragment3 = new Fragment3(); adapter.addItem(fragment3); pager.setAdapter(adapter); //버튼을 클릭했을때 지정한 아이템을 보여준다. Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { pager.setCurrentItem(1); } }); } class MoviePagerAdapter extends FragmentStatePagerAdapter{ ArrayList<Fragment> items = new ArrayList<Fragment>(); //생성자 public MoviePagerAdapter(FragmentManager fm) { super(fm); } //item을 arrayList에 추가 public void addItem(Fragment item){ items.add(item); } //impliments 어뎁터 @Override public Fragment getItem(int position) { return items.get(position); } @Override public int getCount() { return items.size(); } //페이지마다 타이틀을 붙일 수 있다. @Nullable @Override public CharSequence getPageTitle(int position) { return "페이지 " + position; } } }

생각해보기

뷰 페이저에 탭스트립을 추가하면 어떻게 보일까요?

- 탭스트립을 추가해보니 스트립을 누르면 해당 페이저로 이동하게 됩니다.

스트립을 아이콘으로 보여주려면 어떻게 해야 할까요?

- 스트립의 백그라운드에 아이콘을 넣어주면 될것 같습니다.

6. 바로가기 메뉴 만들기

1) 바로가기 메뉴 만들기

프래그먼트 인터페이스.java

public interface FragmentCallback { //프래그먼트의 인덱스 값, 데이터 전달 public void onFragmentSelected(int position, Bundle bundle); }

메인액티비티.java

//네비게이션 리스너를 인터페이스로 구성 public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener,FragmentCallback { Fragement1 fragement1; Fragement2 fragement2; Fragement3 fragement3; Toolbar toolbar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //앱바레이아웃을 사용하면 아래의 코드를 사용 toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); //네비게이션 드로어를 사용하기 위한 기본 설정 DrawerLayout drawer = findViewById(R.id.drawer_layout); ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); drawer.addDrawerListener(toggle); toggle.syncState(); NavigationView navigationView = findViewById(R.id.nav_view); //네비게이션 뷰 내에서 메뉴가 선택되면 호출된다.(onNavigationItemSelected) navigationView.setNavigationItemSelectedListener(this); //프래그먼트 생성 fragement1 = new Fragement1(); fragement2 = new Fragement2(); fragement3 = new Fragement3(); //프래그먼트 매니저로 첫번째 프래그먼트 화면을 컨테이너에 보여준다. getSupportFragmentManager(). beginTransaction().add(R.id.container,fragement1).commit(); } //사용자 정의 인터페이스 구현 @Override public void onFragmentSelected(int position, Bundle bundle) { Fragment curFragment = null; if(position == 0){ curFragment = fragement1; toolbar.setTitle("첫번째 화면"); } else if (position == 1){ curFragment = fragement2; toolbar.setTitle("두번째 화면"); } else if (position ==2){ curFragment = fragement3; toolbar.setTitle("세번째 화면"); } getSupportFragmentManager().beginTransaction(). replace(R.id.container,curFragment).commit(); } @Override public void onBackPressed() { DrawerLayout drawer = 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("StatemetWithEmptyBody") @Override public boolean onNavigationItemSelected(MenuItem item) { // Handle navigation view item clicks here. int id = item.getItemId(); if (id == R.id.nav_0) { Toast.makeText(this,"첫번째 메뉴 선택됨.",Toast.LENGTH_LONG).show(); onFragmentSelected(0,null); } else if (id == R.id.nav_1) { Toast.makeText(this,"두번째 메뉴 선택됨.",Toast.LENGTH_LONG).show(); onFragmentSelected(1,null); } else if (id == R.id.nav_2) { Toast.makeText(this,"번째 메뉴 선택됨.",Toast.LENGTH_LONG).show(); onFragmentSelected(2,null); } DrawerLayout drawer = findViewById(R.id.drawer_layout); drawer.closeDrawer(GravityCompat.START); return true; } }

매인엑티비티.xml

<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"> <androidx.coordinatorlayout.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent" > <com.google.android.material.appbar.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.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/AppTheme.PopupOverlay" /> </com.google.android.material.appbar.AppBarLayout> <FrameLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> </FrameLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout> <!--네비게이션 상단에 보여줄 레이아웃--> <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>

nav_header_main.xml

<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:gravity="bottom" android:orientation="vertical" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingBottom="@dimen/activity_vertical_margin" android:theme="@style/ThemeOverlay.AppCompat.Dark"> <ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:contentDescription="@string/nav_header_desc" android:paddingTop="@dimen/nav_header_vertical_spacing" app:srcCompat="@drawable/profile" /> <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:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/nav_header_subtitle" /> </LinearLayout>

생각해보기

바로가기 메뉴를 볼 수 있게 하는 햄버거 모양 아이콘을 앱의 모든 화면에 넣는 것이 좋을까요?

- 모든 화면에 넣는 것을 비효율 적일 것 같습니다. 필요한 곳에만 사용을 해야한다고 생각합니다.

바로가기 메뉴를 보여주는 것과 옵션 메뉴를 보여주는 것과의 차이점은 무엇일까요?

- 바로가기 메뉴에서는 아무래도 옵션 메뉴에서 보여주는 것보다 공간의 제약이 있어서 많은 것을 보여주지 못하지만, 옵션 메뉴에서는 보다 많은 정보나 메뉴를 보여 줄 수 있다고 생각합니다.

 

 


*********************************************