ViewPager 기반 안드로이드 소개 화면 구현

모바일 앱을 처음 실행할 때 보여지는 소개 페이지는 사용자에게 주요 기능이나 인터페이스를 직관적으로 안내하는 중요한 요소입니다. 일반적으로 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와 간단한 상태 관리를 조합하면 직관적이고 완성도 높은 소개 화면을 구현할 수 있습니다. 필요 시 페이지 전환 애니메이션을 추가하거나, 자동 슬라이딩 기능을 통합하여 더 풍부한 사용자 경험을 제공할 수 있습니다.

태그: Android ViewPager PagerAdapter GuideScreen UserInterface

7월 6일 17:38에 게시됨