기본 RecyclerView 예제
일반적인 애플리케이션에서 작동하는 방식을 RecyclerView
이해하기 위해 이 항목에서는 큰 사진 컬렉션을 표시하는 데 사용하는 RecyclerView
간단한 코드 예제를 살펴봅니다.
RecyclerViewer는 CardView를 사용하여 레이아웃의 RecyclerView
각 사진 항목을 구현합니다. RecyclerView
성능 이점 때문에 이 샘플 앱은 눈에 띄는 지연 없이 대량의 사진 컬렉션을 원활하게 스크롤할 수 있습니다.
예제 데이터 원본
이 예제 앱에서 "사진 앨범" 데이터 원본(클래스가 PhotoAlbum
나타내는)은 항목 콘텐츠를 제공합니다 RecyclerView
.
PhotoAlbum
는 캡션이 있는 사진 모음입니다. 인스턴스화하면 32장의 사진 모음이 준비됩니다.
PhotoAlbum mPhotoAlbum = new PhotoAlbum ();
각 사진 인스턴스는 PhotoAlbum
이미지 리소스 ID PhotoID
및 해당 캡션 문자열 Caption
을 읽을 수 있는 속성을 노출합니다. 사진 컬렉션은 인덱서가 각 사진에 액세스할 수 있도록 구성됩니다. 예를 들어 다음 코드 줄은 컬렉션의 10번째 사진에 대한 이미지 리소스 ID 및 캡션에 액세스합니다.
int imageId = mPhotoAlbum[9].ImageId;
string caption = mPhotoAlbum[9].Caption;
PhotoAlbum
또한 컬렉션의 RandomSwap
첫 번째 사진을 컬렉션의 다른 위치에서 임의로 선택한 사진으로 교환하기 위해 호출할 수 있는 메서드를 제공합니다.
mPhotoAlbum.RandomSwap ();
구현 세부 정보는 PhotoAlbum
이해 RecyclerView
PhotoAlbum
와 관련이 없으므로 소스 코드는 여기에 표시되지 않습니다.
레이아웃 및 초기화
레이아웃 파일 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);
이 코드는 다음을 수행합니다.
데이터 원본을
PhotoAlbum
인스턴스화합니다.사진 앨범 데이터 원본을 어댑터
PhotoAlbumAdapter
의 생성자에 전달합니다(이 가이드의 뒷부분에서 정의됨). 데이터 원본을 매개 변수로 어댑터의 생성자에 전달하는 것이 좋습니다.레이아웃에서
RecyclerView
가져옵니다.위와 같이 메서드를
RecyclerView
호출하여 어댑터를 인스턴스에RecyclerView
SetAdapter
연결합니다.
레이아웃 관리자
각 RecyclerView
항목은 사진 이미지와 사진 캡션이 포함된 항목으로 구성 CardView
됩니다(세부 정보는 아래 보기 소유자 섹션에서 다룹니다). 미리 정의된 LinearLayoutManager
항목은 각각 CardView
세로 스크롤 정렬에 배치하는 데 사용됩니다.
mLayoutManager = new LinearLayoutManager (this);
mRecyclerView.SetLayoutManager (mLayoutManager);
이 코드는 기본 작업의 OnCreate
메서드에 상주합니다. 레이아웃 관리자에 대한 생성자에는 컨텍스트가 필요하므로 MainActivity
위에서 설명한 대로 이를 사용하여 this
전달됩니다.
미리 정의된 LinearLayoutManager
항목을 사용하는 대신 두 CardView
항목을 나란히 표시하는 사용자 지정 레이아웃 관리자를 연결하여 사진 컬렉션을 트래버스하는 페이지 회전 애니메이션 효과를 구현할 수 있습니다. 이 가이드의 뒷부분에서는 다른 레이아웃 관리자에서 교환하여 레이아웃을 수정하는 방법의 예를 볼 수 있습니다.
보기 소유자
뷰 홀더 클래스를 호출 PhotoViewHolder
합니다. 각 PhotoViewHolder
인스턴스는 연결된 행 항목 및 TextView
관련 행 항목에 대한 참조 ImageView
를 보유하며, 여기에 다이어그램으로 배치 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
하여 각 자식 뷰 참조 ImageView
TextView
를 찾고 결과를 각각 및 Caption
속성에 Image
저장합니다. 어댑터는 나중에 이 자식 뷰를 새 데이터로 업데이트할 때 이러한 CardView
속성에서 뷰 참조를 검색합니다.
자세한 RecyclerView.ViewHolder
내용은 RecyclerView.ViewHolder 클래스 참조를 참조하세요.
어댑터
어댑터는 특정 사진에 대한 데이터를 사용하여 각 RecyclerView
행을 로드합니다. 예를 들어 행 위치 P에서 지정된 사진의 경우 어댑터는 데이터 원본 내의 P 위치에 연결된 데이터를 찾아 컬렉션의 P 위치에 있는 행 항목에 RecyclerView
복사합니다. 어댑터는 뷰 홀더를 사용하여 해당 위치에 대한 ImageView
TextView
참조를 조회하므로 사용자가 사진 컬렉션을 스크롤하고 보기를 다시 사용할 때 해당 보기를 반복적으로 호출 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
생성자는 뷰 홀더에서 이전에 설명한 대로 레이아웃에서 자식 뷰에 대한 참조를 찾아 저장합니다.
각 행 항목은 (사진용) 및 (캡션용)이 포함된 ImageView
항목으로 TextView
표시됩니다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; }
}
}
이 코드를 컴파일하고 실행하면 다음 스크린샷과 같이 기본 사진 보기 앱이 만들어집니다.
위의 스크린샷에 표시된 것처럼 그림자가 그려지지 않는 경우 Properties/AndroidManifest.xml 편집하고 요소에 <application>
다음 특성 설정을 추가합니다.
android:hardwareAccelerated="true"
이 기본 앱은 사진 앨범 검색만 지원합니다. 항목 터치 이벤트에는 응답하지 않으며 기본 데이터의 변경 내용을 처리하지도 않습니다. 이 기능은 RecyclerView 확장 예제에 추가됩니다.
LayoutManager 변경
RecyclerView
유연성 때문에 다른 레이아웃 관리자를 사용하도록 앱을 쉽게 수정할 수 있습니다. 다음 예제에서는 세로 선형 레이아웃이 아닌 가로로 스크롤되는 그리드 레이아웃으로 사진 앨범을 표시하도록 수정됩니다. 이를 위해 레이아웃 관리자 인스턴스화는 다음과 같이 사용하도록 GridLayoutManager
수정됩니다.
mLayoutManager = new GridLayoutManager(this, 2, GridLayoutManager.Horizontal, false);
이 코드 변경은 세 LinearLayoutManager
로 GridLayoutManager
를 가로 방향으로 스크롤하는 두 개의 행으로 구성된 그리드를 표시하는 세로로 바꿉니다. 앱을 다시 컴파일하고 실행하면 사진이 그리드에 표시되고 스크롤이 세로가 아닌 가로로 표시되는 것을 볼 수 있습니다.
한 줄의 코드만 변경하면 다른 동작으로 다른 레이아웃을 사용하도록 사진 보기 앱을 수정할 수 있습니다. 레이아웃 스타일을 변경하기 위해 어댑터 코드나 레이아웃 XML을 수정할 필요가 없습니다.
다음 항목인 RecyclerView 예제 확장에서 이 기본 샘플 앱은 항목 클릭 이벤트를 처리하고 기본 데이터 원본이 변경되면 업데이트 RecyclerView
되도록 확장됩니다.