ViewPager 구현하기
ViewPager(뷰 페이저). 좌우로 밀어내는 것으로 프레그먼트 이동이 쉽고, 이쁘기도 해서 카카오톡 등 앱들에서 많이 사용된다.
이번에는 바로 이 뷰 페이저를 만들어보자.
STEP1> 라이브러리 추가
compile 'com.ogaclejapan.smarttablayout:library:1.+@aar'
이름에서 알 수 있듯이, 이 라이브러리는 애니메이션이 아름다운 '탭'을 구현한 라이브러리다.
뷰 페이저는 안드로이드에서 제공하는 android.support.v4.view.ViewPager를 사용한다.
STEP2> 뷰 작성
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="kr.makerj.vmimic.fragment.main.MainActivityFragment">
<com.ogaclejapan.smarttablayout.SmartTabLayout
android:id="@+id/main_viewpagertab"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="#ff0000"
app:stl_indicatorAlwaysInCenter="false"
app:stl_indicatorWithoutPadding="false"
app:stl_indicatorInFront="false"
app:stl_indicatorInterpolation="smart"
app:stl_indicatorGravity="bottom"
app:stl_indicatorColor="#ffffff"
app:stl_indicatorThickness="4dp"
app:stl_indicatorCornerRadius="2dp"
app:stl_overlineColor="#4D000000"
app:stl_overlineThickness="0dp"
app:stl_underlineColor="#4D000000"
app:stl_underlineThickness="1dp"
app:stl_dividerColor="#4D000000"
app:stl_dividerThickness="1dp"
app:stl_defaultTabBackground="?attr/selectableItemBackground"
app:stl_defaultTabTextAllCaps="false"
app:stl_defaultTabTextColor="#ffffff"
app:stl_defaultTabTextSize="12sp"
app:stl_defaultTabTextHorizontalPadding="16dp"
app:stl_defaultTabTextMinWidth="0dp"
app:stl_distributeEvenly="true"
app:stl_clickable="true"
/>
<android.support.v4.view.ViewPager
android:id="@+id/main_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Fragments will be placed here -->
</android.support.v4.view.ViewPager>
</LinearLayout>
위와 같이 작성했다.
중요한 부분은 탭 뷰의
app:stl_defaultTabTextAllCaps="false"
로, 탭에 들어갈 문자열을 자동 대문자화 하는 옵션인데, 이게 탭에 아이콘을 활용하지 못하게 한다. 따라서 false로 변경한다.
나머지 옵션들은 이름에서 무슨 의미진지 유추 가능할 것이다.
android.support.v4.view.ViewPager는 딱히 설정할 게 없다. 이 뷰 페이저에는 실제 뷰인 프레그먼트들이 들어간다.
뷰 페이저 안에 들어갈 프레그먼트들은 알아서(...) 만들어두고, 다 만들었으면 STEP3로
STEP3> 뷰 페이저 어뎁터 설정
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.fragment_main, container, false);
final List<_Fragment> fragments = new ArrayList<>();
fragments.add(HomeFragment.newInstance(null, null));
fragments.add(InterestFragment.newInstance());
fragments.add(PopularFragment.newInstance());
fragments.add(MyProfileFragment.newInstance());
FragmentPagerAdapter adapter = new FragmentPagerAdapter(getActivity().getSupportFragmentManager()) {
@Override
public CharSequence getPageTitle(int position) {
return fragments.get(position).getTitle(getActivity());
}
@Override
public Fragment getItem(int position) {
return fragments.get(position);
}
@Override
public int getCount() {
return fragments.size();
}
};
getActivity().setTitle(fragments.get(0).getTitle(getActivity()));
ViewPager pager = (ViewPager) layout.findViewById(R.id.main_viewpager);
pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
getActivity().setTitle(fragments.get(position).getTitle(getActivity()));
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
pager.setAdapter(adapter);
((SmartTabLayout) layout.findViewById(R.id.main_viewpagertab)).setViewPager(pager);
return layout;
}
나는 액티비티가 아니라, android.support.v4.app.Fragment프레그먼트. 즉 호환성 프레그먼트에 뷰 페이저를 넣어서 작성했다. 액티비티를 기반으로 개발하고 있다면 액티비티의 onCreate에 적용하자. 또한 호환성 라이브러리를 사용하고 있지 않다면 Support와 관련된 메소드를 사용하지 말 것.
코드를 순서대로 설명하자면,
- 프레그먼트 리스트 생성. 프레그먼트에 접근할 일이 많아서 리스트를 사용했다
- FragmentPagerAdapter생성 및 설정. PagerAdapter는 사용하지 않는다. 여기선 프레그먼트를 넣은 뷰 페이저를 사용할것이기 때문
- getPageTitle구현. 이게 있어야 탭이 타이틀을 인식한다. 반드시 구현할 것. 참고로 프레그먼트에 getTitle()메소드는 없다. 내가 만든거다. 적당히 제목을 반환하도록 만들자.
- getItem과 getCount를 구현한다. 리스트에 접근만 하면 되니. 딱히 할거 없다 위와 같이 구현하자.
- 페이지를 넘길 때, 적절히 액션바의 제목이 프레그먼트의 타이틀을 따라가도록 하자.
- getActivity().setTitle(fragments.get(0).getTitle(getActivity())) 초기값 설정. 첫 번째 페이지의 타이틀을 설정해주자.
- ViewPager.OnPageChangeListener의 onPageSelected를 작성한다. 이 코드가 페이지가 넘겨겼을 때 마다 액션바의 제목이 바뀌게 해준다.
- pager.setAdapter(adapter) 이제 뷰 페이저에 어뎁터를 설정해 주고,
- ((SmartTabLayout) layout.findViewById(R.id.뷰_페이저_아이디)).setViewPager(pager) 탭에 뷰 페이저를 설정해 주면 된다.
부록> 탭에 타이틀로 아이콘도 사용하고 싶다!
안드로이드는 보통 제목과 같은 문자열을 다룰 때, String이 아닌 CharSequence를 사용하고 있다.
안드로이드는 String같은 단순 문자열 뿐만 아니라 SpannableString과 같은 이미지를 포함한 문자열을 표현할 수 있다는 것을 잊지 말자.
따라서 return "프레그먼트1타이틀"과 같이 칙칙한 디자인을 유도하는 코드가 싫은 멋쟁이들은 아래와 같이 하자.
public class ViewUtil {
public static int TEXT_SIZE = -1;
public static int TEXT_SIZE_BIG = -1;
public static Drawable drawable(Context context, int id) {
if (TEXT_SIZE == -1) {
TEXT_SIZE = (int) new TextView(context).getTextSize();
TEXT_SIZE_BIG = (int) (TEXT_SIZE * 1.5);
}
if (Build.VERSION.SDK_INT >= 21) {
return context.getResources().getDrawable(id, context.getTheme());
} else {
return context.getResources().getDrawable(id);
}
}
public static CharSequence iconText(Drawable icon, String text) {
SpannableString iconText = new SpannableString(" "+text);
icon.setBounds(0, 0, TEXT_SIZE_BIG, TEXT_SIZE_BIG);
ImageSpan imageSpan = new ImageSpan(icon);
iconText.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return iconText;
}
}
많은 프레그먼트에서 호출될 테니, 아예 유틸리티 클래스로 작성했다. iconText에서 하는 일은 간단하다.
- SpannableString로 먼저 텍스트를 설정한다. 아이콘만 사용할 생각이라면 ""을 사용하자. 참고로 " " + text과 같이 한칸 띄어쓰기를 한 이유는, 한칸이 바로 아이콘의 자리이기 때문이다. 따라서 띄어쓰기 안하면 한 문자가 아이콘에 의해 가려진다.
- setBounds로 아이콘의 크기를 지정한다. 기본 문자열 크기의 1.5배가 적절하다
- 나머지 부분은 이미지 부분과 텍스트 부분을 합치는 것으로 큰 의미는 없다.
프레그먼트에서의 사용은?
public CharSequence getTitle(Context context) {
return ViewUtil.iconText(ViewUtil.drawable(context, R.drawable.ic_person_white_48dp), "MY");
}
프레그먼트에서의 사용은 이렇게 했다.
'Android > Application' 카테고리의 다른 글
Toolbar 사용하기 (0) | 2015.09.24 |
---|---|
프레그먼트에서 메뉴 사용하기 (0) | 2015.09.24 |
Android SearchView (0) | 2015.09.23 |
안드로이드 상태바 색상 변경 (0) | 2015.09.23 |
바코드, QR코드 생성 (0) | 2015.09.22 |