모바일 앱을 처음 실행할 때 보여지는 소개 페이지는 사용자에게 주요 기능이나 인터페이스를 직관적으로 안내하는 중요한 요소입니다. 일반적으로 3~4장의 이미지를 가로로 스크롤하며 확인하고, 마지막 페이지에서 '시작하기' 버튼을 통해 본격적인 사용을 시작할 수 있도록 구성됩니다. 이 기능은 안드로이드의 ViewPager를 활용하면 간단히 구현할 수 있습니다.
준비 작업
프로젝트 생성 후, app/libs 폴더에 androidx.viewpager:1.0.0 또는 기존의 android-support-v4.jar가 포함되어 있는지 확인합니다. 최신 프로젝트라면 Gradle 의존성에 아래와 같이 추가하는 것을 권장합니다:
implementation 'androidx.viewpager:viewpager:1.0.0'
다음으로 소개 화면에 사용할 이미지 파일(welcome_1 ~ welcome_4)과 하단의 인디케이터용 점 모양 이미지 두 종류(dot_selected, dot_unselected)를 res/drawable 디렉터리에 넣습니다.
레이아웃 설계 (activity_welcome.xml)
전체 레이아웃은 상대 배치(RelativeLayout)를 기반으로, 중앙에 ViewPager를 배치하고, 하단에는 인디케이터와 시작 버튼을 정렬합니다.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.viewpager.widget.ViewPager
android:id="@+id/pager_guide"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="@+id/layout_dots"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="30dp"
android:orientation="horizontal" />
<Button
android:id="@+id/btn_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/layout_dots"
android:layout_centerHorizontal="true"
android:layout_marginBottom="50dp"
android:text="시작하기"
android:visibility="gone"
android:paddingHorizontal="24dp"
android:paddingVertical="12dp" />
</RelativeLayout>
PagerAdapter 커스터마이징
화면 전환을 위해 PagerAdapter를 확장한 어댑터를 작성합니다. 각 페이지는 ImageView로 구성되며, 리스트 형태로 관리됩니다.
public class GuidePagerAdapter extends PagerAdapter {
private final List<View> pageViews;
public GuidePagerAdapter(List<View> views) {
this.pageViews = views;
}
@Override
public int getCount() {
return pageViews.size();
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
View view = pageViews.get(position);
container.addView(view);
return view;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView((View) object);
}
}
선택 상태에 따른 점 표시 처리
하단 점의 색상을 상태에 따라 다르게 표현하기 위해 선택기 리소스를 사용합니다. res/drawable/indicator_dot.xml 파일을 생성합니다.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/dot_selected" android:state_enabled="false" />
<item android:drawable="@drawable/dot_unselected" android:state_enabled="true" />
</selector>
메인 액티비티 로직 (WelcomeActivity.java)
액티비티에서는 뷰 페이저 초기화, 인디케이터 동적 생성, 페이지 변경 감지 등을 처리합니다.
public class WelcomeActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener, View.OnClickListener {
private ViewPager viewPager;
private GuidePagerAdapter adapter;
private Button startButton;
private ImageView[] indicators;
private int currentPageIndex;
// 소개 이미지 리소스 ID 배열
private static final int[] GUIDE_IMAGES = {
R.drawable.welcome_1,
R.drawable.welcome_2,
R.drawable.welcome_3,
R.drawable.welcome_4
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_welcome);
initializeViews();
setupViewPager();
createIndicators();
}
private void initializeViews() {
startButton = findViewById(R.id.btn_start);
startButton.setOnClickListener(v -> {
Toast.makeText(this, "앱으로 이동합니다.", Toast.LENGTH_SHORT).show();
finish(); // 또는 다음 액티비티로 전환
});
}
private void setupViewPager() {
viewPager = findViewById(R.id.pager_guide);
List<View> pages = new ArrayList<>();
for (int resId : GUIDE_IMAGES) {
ImageView imageView = new ImageView(this);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setImageResource(resId);
pages.add(imageView);
}
adapter = new GuidePagerAdapter(pages);
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(this);
}
private void createIndicators() {
LinearLayout dotsContainer = findViewById(R.id.layout_dots);
indicators = new ImageView[GUIDE_IMAGES.length];
for (int i = 0; i < indicators.length; i++) {
indicators[i] = new ImageView(this);
indicators[i].setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
indicators[i].setPadding(12, 0, 12, 0);
indicators[i].setImageResource(R.drawable.indicator_dot);
indicators[i].setEnabled(true);
indicators[i].setOnClickListener(this);
indicators[i].setTag(i);
dotsContainer.addView(indicators[i]);
}
currentPageIndex = 0;
indicators[currentPageIndex].setEnabled(false);
}
@Override
public void onPageSelected(int position) {
updateIndicators(position);
if (position == GUIDE_IMAGES.length - 1) {
startButton.setVisibility(View.VISIBLE);
} else {
startButton.setVisibility(View.GONE);
}
}
private void updateIndicators(int position) {
indicators[currentPageIndex].setEnabled(true);
indicators[position].setEnabled(false);
currentPageIndex = position;
}
@Override
public void onClick(View v) {
Integer pos = (Integer) v.getTag();
if (pos != null) {
viewPager.setCurrentItem(pos);
}
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
@Override
public void onPageScrollStateChanged(int state) {}
}
이처럼 ViewPager와 간단한 상태 관리를 조합하면 직관적이고 완성도 높은 소개 화면을 구현할 수 있습니다. 필요 시 페이지 전환 애니메이션을 추가하거나, 자동 슬라이딩 기능을 통합하여 더 풍부한 사용자 경험을 제공할 수 있습니다.