다음을 통해 공유


기본 RecyclerView 예제

일반적인 애플리케이션에서 작동하는 방식을 RecyclerView 이해하기 위해 이 항목에서는 큰 사진 컬렉션을 표시하는 데 사용하는 RecyclerView 간단한 코드 예제를 살펴봅니다.

CardView를 사용하여 사진을 표시하는 RecyclerView 앱의 두 스크린샷

RecyclerViewer는 CardView를 사용하여 레이아웃의 RecyclerView 각 사진 항목을 구현합니다. RecyclerView성능 이점 때문에 이 샘플 앱은 눈에 띄는 지연 없이 대량의 사진 컬렉션을 원활하게 스크롤할 수 있습니다.

예제 데이터 원본

이 예제 앱에서 "사진 앨범" 데이터 원본(클래스가 PhotoAlbum 나타내는)은 항목 콘텐츠를 제공합니다 RecyclerView . PhotoAlbum은 캡션이 있는 사진 모음입니다. 인스턴스화하면 32장의 사진 모음을 얻을 수 있습니다.

PhotoAlbum mPhotoAlbum = new PhotoAlbum ();

각 사진 인스턴스는 PhotoAlbum 이미지 리소스 ID PhotoID및 해당 캡션 문자열Caption을 읽을 수 있는 속성을 노출합니다. 사진 컬렉션은 인덱서가 각 사진에 액세스할 수 있도록 구성됩니다. 예를 들어 다음 코드 줄은 이미지 리소스 ID에 액세스하고 컬렉션의 10번째 사진에 대한 캡션.

int imageId = mPhotoAlbum[9].ImageId;
string caption = mPhotoAlbum[9].Caption;

PhotoAlbum 또한 컬렉션의 RandomSwap 첫 번째 사진을 컬렉션의 다른 위치에서 임의로 선택한 사진으로 교환하기 위해 호출할 수 있는 메서드를 제공합니다.

mPhotoAlbum.RandomSwap ();

구현 세부 정보는 PhotoAlbum 이해 RecyclerViewPhotoAlbum 와 관련이 없으므로 소스 코드는 여기에 표시되지 않습니다.

레이아웃 및 초기화

레이아웃 파일 Main.axml은 다음 내의 단일 RecyclerView 파일로 LinearLayout구성됩니다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:scrollbars="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
</LinearLayout>

지원 라이브러리에 패키지되어 있으므로 RecyclerView 정규화된 이름 android.support.v7.widget.RecyclerView를 사용해야 합니다. 이 OnCreate 레이아웃을 초기화하고, 어댑터를 인스턴스화하고, 기본 데이터 원본을 준비하는 방법입니다 MainActivity .

public class MainActivity : Activity
{
    RecyclerView mRecyclerView;
    RecyclerView.LayoutManager mLayoutManager;
    PhotoAlbumAdapter mAdapter;
    PhotoAlbum mPhotoAlbum;

    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);

        // Prepare the data source:
        mPhotoAlbum = new PhotoAlbum ();

        // Instantiate the adapter and pass in its data source:
        mAdapter = new PhotoAlbumAdapter (mPhotoAlbum);

        // Set our view from the "main" layout resource:
        SetContentView (Resource.Layout.Main);

        // Get our RecyclerView layout:
        mRecyclerView = FindViewById<RecyclerView> (Resource.Id.recyclerView);

        // Plug the adapter into the RecyclerView:
        mRecyclerView.SetAdapter (mAdapter);

이 코드는 다음을 수행합니다.

  1. 데이터 원본을 PhotoAlbum 인스턴스화합니다.

  2. 사진 앨범 데이터 원본을 어댑터 PhotoAlbumAdapter 의 생성자에 전달합니다(이 가이드의 뒷부분에서 정의됨). 데이터 원본을 매개 변수로 어댑터의 생성자에 전달하는 것이 좋습니다.

  3. 레이아웃에서 RecyclerView 가져옵니다.

  4. 위와 같이 메서드를 RecyclerView 호출하여 어댑터를 인스턴스에 RecyclerViewSetAdapter 연결합니다.

레이아웃 관리자

RecyclerView 항목은 사진 이미지 및 사진 캡션 포함된 항목으로 구성 CardView 됩니다(세부 정보는 아래의 뷰 홀더 섹션에서 다룹니다). 미리 정의된 LinearLayoutManager 항목은 각각 CardView 세로 스크롤 정렬에 배치하는 데 사용됩니다.

mLayoutManager = new LinearLayoutManager (this);
mRecyclerView.SetLayoutManager (mLayoutManager);

이 코드는 기본 활동의 OnCreate 메서드에 상주합니다. 레이아웃 관리자에 대한 생성자에는 컨텍스트필요하므로 MainActivity 위에서 설명한 대로 이를 사용하여 this 전달됩니다.

미리 정의된 LinearLayoutManager항목을 사용하는 대신 두 CardView 항목을 나란히 표시하는 사용자 지정 레이아웃 관리자를 연결하여 사진 컬렉션을 트래버스하는 페이지 회전 애니메이션 효과를 구현할 수 있습니다. 이 가이드의 뒷부분에서는 다른 레이아웃 관리자에서 교환하여 레이아웃을 수정하는 방법의 예를 볼 수 있습니다.

보기 소유자

뷰 홀더 클래스를 호출 PhotoViewHolder합니다. 각 PhotoViewHolder 인스턴스는 연결된 행 항목 및 TextView 관련 행 항목에 대한 참조 ImageView 를 보유하며, 여기에 다이어그램으로 배치 CardView 됩니다.

ImageView 및 TextView를 포함하는 CardView 다이어그램

PhotoViewHolder 는 위의 레이아웃에 RecyclerView.ViewHolder 표시된 참조 ImageView 를 저장할 속성을 파생시키고 TextView 포함합니다. PhotoViewHolder 는 두 개의 속성과 하나의 생성자로 구성됩니다.

public class PhotoViewHolder : RecyclerView.ViewHolder
{
    public ImageView Image { get; private set; }
    public TextView Caption { get; private set; }

    public PhotoViewHolder (View itemView) : base (itemView)
    {
        // Locate and cache view references:
        Image = itemView.FindViewById<ImageView> (Resource.Id.imageView);
        Caption = itemView.FindViewById<TextView> (Resource.Id.textView);
    }
}

이 코드 예제 PhotoViewHolder 에서 생성자는 래핑하는 부모 항목 뷰()에 CardView대한 참조를 PhotoViewHolder 전달합니다. 항상 부모 항목 뷰를 기본 생성자로 전달합니다. PhotoViewHolder 생성자는 부모 항목 뷰를 호출 FindViewById 하여 각 자식 뷰 참조 ImageViewTextView를 찾고 결과를 각각 및 Caption 속성에 Image 저장합니다. 어댑터는 나중에 이 자식 뷰를 새 데이터로 업데이트할 때 이러한 CardView속성에서 뷰 참조를 검색합니다.

자세한 RecyclerView.ViewHolder내용은 RecyclerView.ViewHolder 클래스 참조를 참조하세요.

어댑터

어댑터는 특정 사진에 대한 데이터를 사용하여 각 RecyclerView 행을 로드합니다. 예를 들어 행 위치 P에서 지정된 사진의 경우 어댑터는 데이터 원본 내의 P 위치에 연결된 데이터를 찾아 컬렉션의 P 위치에 있는 행 항목에 RecyclerView 복사합니다. 어댑터는 뷰 홀더를 사용하여 해당 위치에 대한 ImageViewTextView 참조를 조회하므로 사용자가 사진 컬렉션을 스크롤하고 보기를 다시 사용할 때 해당 보기를 반복적으로 호출 FindViewById 할 필요가 없습니다.

RecyclerViewer에서 어댑터 클래스는 다음을 만들기 PhotoAlbumAdapter위해 파생됩니다RecyclerView.Adapter.

public class PhotoAlbumAdapter : RecyclerView.Adapter
{
    public PhotoAlbum mPhotoAlbum;

    public PhotoAlbumAdapter (PhotoAlbum photoAlbum)
    {
        mPhotoAlbum = photoAlbum;
    }
    ...
}

멤버는 mPhotoAlbum 생성자에 전달되는 데이터 원본(사진 앨범)을 포함하고 생성자는 사진 앨범을 이 멤버 변수에 복사합니다. 다음 필수 RecyclerView.Adapter 메서드가 구현됩니다.

  • OnCreateViewHolder – 항목 레이아웃 파일 및 보기 소유자를 인스턴스화합니다.

  • OnBindViewHolder – 지정된 위치에 있는 데이터를 해당 참조가 지정된 뷰 소유자에 저장되는 뷰에 로드합니다.

  • ItemCount – 데이터 원본의 항목 수를 반환합니다.

레이아웃 관리자는 항목의 위치를 지정하는 동안 이러한 메서드를 RecyclerView호출합니다. 이러한 메서드의 구현은 다음 섹션에서 검토합니다.

OnCreateViewHolder

레이아웃 관리자는 항목을 나타내기 위해 새 뷰 홀더가 필요할 때 RecyclerView 호출 OnCreateViewHolder 합니다. OnCreateViewHolder 는 보기의 레이아웃 파일에서 항목 보기를 확장하여 새 PhotoViewHolder 인스턴스에서 보기를 래핑합니다. PhotoViewHolder 생성자는 뷰 홀더에서 이전에 설명한 대로 레이아웃에서 자식 뷰에 대한 참조를 찾아 저장합니다.

각 행 항목은 (사진용) 및 TextView (캡션)가 포함된 ImageView 항목으로 표시됩니다CardView. 이 레이아웃은 PhotoCardView.axml 파일에 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:card_view="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        card_view:cardElevation="4dp"
        card_view:cardUseCompatPadding="true"
        card_view:cardCornerRadius="5dp">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="8dp">
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/imageView"
                android:scaleType="centerCrop" />
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:textColor="#333333"
                android:text="Caption"
                android:id="@+id/textView"
                android:layout_gravity="center_horizontal"
                android:layout_marginLeft="4dp" />
        </LinearLayout>
    </android.support.v7.widget.CardView>
</FrameLayout>

이 레이아웃은 .의 RecyclerView단일 행 항목을 나타냅니다. 아래 설명된 메서드는 OnBindViewHolder 데이터 원본의 데이터를 이 레이아웃과 TextView 레이아웃으로 ImageView 복사합니다. OnCreateViewHolder는 지정된 사진 위치에 RecyclerView 대해 이 레이아웃을 확장하여 새 PhotoViewHolder 인스턴스를 인스턴스화합니다(연결된 레이아웃에서 자 CardView 식 보기 및 TextView 자식 보기에 대한 참조 ImageView 를 찾아 캐시).

public override RecyclerView.ViewHolder
    OnCreateViewHolder (ViewGroup parent, int viewType)
{
    // Inflate the CardView for the photo:
    View itemView = LayoutInflater.From (parent.Context).
                Inflate (Resource.Layout.PhotoCardView, parent, false);

    // Create a ViewHolder to hold view references inside the CardView:
    PhotoViewHolder vh = new PhotoViewHolder (itemView);
    return vh;
}

결과 뷰 홀더 인스턴스 vh는 호출자(레이아웃 관리자)에게 다시 반환됩니다.

OnBindViewHolder

레이아웃 관리자가 표시되는 화면 영역에 특정 보기를 RecyclerView표시할 준비가 되면 어댑터의 메서드를 호출하여 지정된 행 위치에 있는 항목을 데이터 원본의 OnBindViewHolder 콘텐츠로 채웁니다. OnBindViewHolder지정된 행 위치(사진의 이미지 리소스 및 사진 캡션 문자열)에 대한 사진 정보를 가져오고 이 데이터를 연결된 보기에 복사합니다. 뷰는 뷰 소유자 개체(매개 변수를 통해 전달됨)에 저장된 참조를 holder 통해 위치합니다.

public override void
    OnBindViewHolder (RecyclerView.ViewHolder holder, int position)
{
    PhotoViewHolder vh = holder as PhotoViewHolder;

    // Load the photo image resource from the photo album:
    vh.Image.SetImageResource (mPhotoAlbum[position].PhotoID);

    // Load the photo caption from the photo album:
    vh.Caption.Text = mPhotoAlbum[position].Caption;
}

전달된 뷰 소유자 개체를 사용하려면 먼저 파생된 뷰 소유자 형식(이 경우 PhotoViewHolder)으로 캐스팅해야 합니다. 어댑터는 이미지 리소스를 뷰 소유자의 Image 속성에서 참조하는 보기에 로드하고 캡션 텍스트를 뷰 소유자의 Caption 속성이 참조하는 보기에 복사합니다. 연결된 뷰를 해당 데이터와 바인딩합니다.

OnBindViewHolder 데이터 구조를 직접 처리하는 코드입니다. 이 경우 OnBindViewHolder 데이터 원본의 RecyclerView 연결된 데이터 항목에 항목 위치를 매핑하는 방법을 이해합니다. 이 경우 위치가 사진 앨범의 배열 인덱스로 사용될 수 있으므로 매핑이 간단합니다. 그러나 더 복잡한 데이터 원본은 이러한 매핑을 설정하기 위해 추가 코드가 필요할 수 있습니다.

ItemCount

이 메서드는 ItemCount 데이터 컬렉션의 항목 수를 반환합니다. 예제 사진 뷰어 앱에서 항목 수는 사진 앨범의 사진 수입니다.

public override int ItemCount
{
    get { return mPhotoAlbum.NumPhotos; }
}

자세한 RecyclerView.Adapter내용은 RecyclerView.Adapter 클래스 참조를 참조하세요.

모두 함께 배치

예제 사진 앱의 결과 RecyclerView 구현은 데이터 원본, 레이아웃 관리자 및 어댑터를 만드는 코드로 구성됩니다 MainActivity . MainActivity 인스턴스를 mRecyclerView 만들고, 데이터 원본과 어댑터를 인스턴스화하고, 레이아웃 관리자 및 어댑터에 연결합니다.

public class MainActivity : Activity
{
    RecyclerView mRecyclerView;
    RecyclerView.LayoutManager mLayoutManager;
    PhotoAlbumAdapter mAdapter;
    PhotoAlbum mPhotoAlbum;

    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);
        mPhotoAlbum = new PhotoAlbum();
        SetContentView (Resource.Layout.Main);
        mRecyclerView = FindViewById<RecyclerView> (Resource.Id.recyclerView);

        // Plug in the linear layout manager:
        mLayoutManager = new LinearLayoutManager (this);
        mRecyclerView.SetLayoutManager (mLayoutManager);

        // Plug in my adapter:
        mAdapter = new PhotoAlbumAdapter (mPhotoAlbum);
        mRecyclerView.SetAdapter (mAdapter);
    }
}

PhotoViewHolder 뷰 참조를 찾아 캐시합니다.

public class PhotoViewHolder : RecyclerView.ViewHolder
{
    public ImageView Image { get; private set; }
    public TextView Caption { get; private set; }

    public PhotoViewHolder (View itemView) : base (itemView)
    {
        // Locate and cache view references:
        Image = itemView.FindViewById<ImageView> (Resource.Id.imageView);
        Caption = itemView.FindViewById<TextView> (Resource.Id.textView);
    }
}

PhotoAlbumAdapter 는 다음 세 가지 필수 메서드 재정의를 구현합니다.

public class PhotoAlbumAdapter : RecyclerView.Adapter
{
    public PhotoAlbum mPhotoAlbum;
    public PhotoAlbumAdapter (PhotoAlbum photoAlbum)
    {
        mPhotoAlbum = photoAlbum;
    }

    public override RecyclerView.ViewHolder
        OnCreateViewHolder (ViewGroup parent, int viewType)
    {
        View itemView = LayoutInflater.From (parent.Context).
                    Inflate (Resource.Layout.PhotoCardView, parent, false);
        PhotoViewHolder vh = new PhotoViewHolder (itemView);
        return vh;
    }

    public override void
        OnBindViewHolder (RecyclerView.ViewHolder holder, int position)
    {
        PhotoViewHolder vh = holder as PhotoViewHolder;
        vh.Image.SetImageResource (mPhotoAlbum[position].PhotoID);
        vh.Caption.Text = mPhotoAlbum[position].Caption;
    }

    public override int ItemCount
    {
        get { return mPhotoAlbum.NumPhotos; }
    }
}

이 코드를 컴파일하고 실행하면 다음 스크린샷과 같이 기본 사진 보기 앱이 만들어집니다.

세로 스크롤 사진 카드 있는 사진 보기 앱의 스크린샷 2개

위의 스크린샷에 표시된 것처럼 그림자가 그려지지 않는 경우 Properties/AndroidManifest.xml 편집하고 요소에 <application> 다음 특성 설정을 추가합니다.

android:hardwareAccelerated="true"

이 기본 앱은 사진 앨범 검색만 지원합니다. 항목 터치 이벤트에는 응답하지 않으며 기본 데이터의 변경 내용을 처리하지도 않습니다. 이 기능은 RecyclerView 확장 예제추가됩니다.

LayoutManager 변경

RecyclerView유연성 때문에 다른 레이아웃 관리자를 사용하도록 앱을 쉽게 수정할 수 있습니다. 다음 예제에서는 세로 선형 레이아웃이 아닌 가로로 스크롤되는 그리드 레이아웃으로 사진 앨범을 표시하도록 수정됩니다. 이를 위해 레이아웃 관리자 인스턴스화는 다음과 같이 사용하도록 GridLayoutManager 수정됩니다.

mLayoutManager = new GridLayoutManager(this, 2, GridLayoutManager.Horizontal, false);

이 코드 변경은 세 LinearLayoutManagerGridLayoutManager 를 가로 방향으로 스크롤하는 두 개의 행으로 구성된 그리드를 표시하는 세로로 바꿉니다. 앱을 다시 컴파일하고 실행하면 사진이 그리드에 표시되고 스크롤이 세로가 아닌 가로로 표시되는 것을 볼 수 있습니다.

그리드에 가로 스크롤 사진이 있는 앱의 예제 스크린샷

한 줄의 코드만 변경하면 다른 동작으로 다른 레이아웃을 사용하도록 사진 보기 앱을 수정할 수 있습니다. 레이아웃 스타일을 변경하기 위해 어댑터 코드나 레이아웃 XML을 수정할 필요가 없습니다.

다음 항목인 RecyclerView 예제 확장에서 이 기본 샘플 앱은 항목 클릭 이벤트를 처리하고 기본 데이터 원본이 변경되면 업데이트 RecyclerView 되도록 확장됩니다.