RecyclerView 예제 확장

기본 RecyclerView 예제설명된 기본 앱은 실제로 많은 작업을 수행하지 않습니다. 단순히 스크롤하고 사진 항목의 고정 목록을 표시하여 검색을 용이하게 합니다. 실제 애플리케이션에서 사용자는 디스플레이의 항목을 탭하여 앱과 상호 작용할 수 있기를 기대합니다. 또한 기본 데이터 원본은 변경되거나 앱에서 변경될 수 있으며, 디스플레이의 내용은 이러한 변경 내용과 일치해야 기본. 다음 섹션에서는 항목 클릭 이벤트를 처리하고 기본 데이터 원본이 변경되면 업데이트 RecyclerView 하는 방법을 알아봅니다.

항목 클릭 이벤트 처리

사용자가 항목 RecyclerView에 터치하면 항목 클릭 이벤트가 생성되어 앱에 어떤 항목이 터치되었는지 알립니다. 이 이벤트는 생성 RecyclerView 되지 않습니다. 대신 보기 소유자에 래핑된 항목 보기는 터치를 감지하고 이러한 터치를 클릭 이벤트로 보고합니다.

항목 클릭 이벤트를 처리하는 방법을 설명하기 위해 다음 단계에서는 사용자가 터치한 사진을 보고하도록 기본 사진 보기 앱을 수정하는 방법을 설명합니다. 샘플 앱에서 항목 클릭 이벤트가 발생하면 다음 시퀀스가 발생합니다.

  1. 사진은 CardView 항목 클릭 이벤트를 감지하고 어댑터에 알립니다.

  2. 어댑터는 이벤트(항목 위치 정보 포함)를 활동의 항목 클릭 처리기로 전달합니다.

  3. 활동의 항목 클릭 처리기가 항목 클릭 이벤트에 응답합니다.

먼저 호출 ItemClick 된 이벤트 처리기 멤버가 클래스 정의에 PhotoAlbumAdapter 추가됩니다.

public event EventHandler<int> ItemClick;

다음으로 항목 클릭 이벤트 처리기 메서드가 추가 MainActivity됩니다. 이 처리기는 터치된 사진 항목을 나타내는 알림을 간략하게 표시합니다.

void OnItemClick (object sender, int position)
{
    int photoNum = position + 1;
    Toast.MakeText(this, "This is photo number " + photoNum, ToastLength.Short).Show();
}

다음으로, 처리기를 PhotoAlbumAdapter.에 등록하려면 코드 줄이 OnItemClick 필요합니다. 이 작업을 수행하는 좋은 위치는 만들어진 직후 PhotoAlbumAdapter 입니다.

mAdapter = new PhotoAlbumAdapter (mPhotoAlbum);
mAdapter.ItemClick += OnItemClick;

이 기본 예제에서 처리기 등록은 기본 작업의 OnCreate 메서드에서 수행되지만 프로덕션 앱은 OnResume 처리기를 등록하고 등록을 취소할 OnPause 수 있습니다. 자세한 내용은 활동 수명 주기를 참조하세요.

PhotoAlbumAdapter 는 이제 항목 클릭 이벤트를 수신할 때 호출 OnItemClick 됩니다. 다음 단계는 이 ItemClick 이벤트를 발생시키는 어댑터에서 처리기를 만드는 것입니다. 다음 메서드 OnClick는 어댑터 메서드 ItemCount 바로 다음에 추가됩니다.

void OnClick (int position)
{
    if (ItemClick != null)
        ItemClick (this, position);
}

OnClick 메서드는 항목 보기에서 항목 클릭 이벤트에 대 한 어댑터의 수신기 입니다. 항목 보기의 뷰 소유자 PhotoViewHolder 를 통해 항목 보기에 이 수신기를 등록하려면 먼저 이 메서드를 추가 인수로 수락하고 항목 보기 Click 이벤트에 등록 OnClick 하도록 생성자를 수정해야 합니다. 수정된 PhotoViewHolder 생성자는 다음과 같습니다.

public PhotoViewHolder (View itemView, Action<int> listener)
    : base (itemView)
{
    Image = itemView.FindViewById<ImageView> (Resource.Id.imageView);
    Caption = itemView.FindViewById<TextView> (Resource.Id.textView);

    itemView.Click += (sender, e) => listener (base.LayoutPosition);
}

매개 변수에는 itemView 사용자가 터치한 매개 변수에 대한 참조 CardView 가 포함됩니다. 뷰 홀더 기본 클래스는 (속성을 통해LayoutPosition) 나타내는 항목(CardView)의 레이아웃 위치를 알고 있으며, 항목 클릭 이벤트가 발생할 때 이 위치는 어댑터의 OnClick 메서드에 전달됩니다. 어댑터의 OnCreateViewHolder 메서드가 뷰 홀더의 생성자에 어댑터의 OnClick 메서드를 전달하도록 수정됩니다.

PhotoViewHolder vh = new PhotoViewHolder (itemView, OnClick);

이제 샘플 사진 보기 앱을 빌드하고 실행할 때 디스플레이에서 사진을 탭하면 어떤 사진이 터치되었는지 보고하는 알림이 표시됩니다.

Example Toast that appears when a photo Card is tapped

이 예제에서는 이벤트 처리기를 구현하기 위한 한 가지 방법만 보여 RecyclerView줍니다. 여기에서 사용할 수 있는 또 다른 방법은 뷰 홀더에 이벤트를 배치하고 어댑터가 이러한 이벤트를 구독하도록 하는 것입니다. 샘플 사진 앱에서 사진 편집 기능을 제공하는 경우 각각에 대해 ImageView 별도의 이벤트가 필요합니다. 터치 TextView 하면 사용자가 캡션 편집할 수 있는 대화 상자가 시작 EditView 되고 ImageView 사용자가 사진을 자르거나 회전할 수 있는 사진 터치업 도구가 시작 TextView 됩니다.CardView 앱의 요구 사항에 따라 터치 이벤트를 처리하고 응답하기 위한 최상의 방법을 디자인해야 합니다.

데이터 세트가 변경될 때 업데이트할 수 있는 방법을 RecyclerView 보여주기 위해 샘플 사진 보기 앱을 수정하여 데이터 원본에서 사진을 임의로 선택하고 첫 번째 사진과 교환할 수 있습니다. 먼저, 임의 선택 단추가 예제 사진 앱의 Main.axml 레이아웃에 추가됩니다.

<?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">
    <Button
        android:id="@+id/randPickButton"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Random Pick" />
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:scrollbars="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
</LinearLayout>

다음으로, 기본 작업 메서드의 OnCreate 끝에 코드가 추가되어 레이아웃에서 단추를 찾고 Random Pick 처리기를 연결합니다.

Button randomPickBtn = FindViewById<Button>(Resource.Id.randPickButton);

randomPickBtn.Click += delegate
{
    if (mPhotoAlbum != null)
    {
        // Randomly swap a photo with the first photo:
        int idx = mPhotoAlbum.RandomSwap();
    }
};

이 처리기는 임의 선택 단추를 탭할 때 사진 앨범의 RandomSwap 메서드를 호출합니다. 이 메서드는 RandomSwap 무작위로 사진을 데이터 원본의 첫 번째 사진과 교환한 다음 임의로 교환된 사진의 인덱스를 반환합니다. 이 코드를 사용하여 샘플 앱을 컴파일하고 실행하는 경우 임의 선택 단추를 탭해도 데이터 원본의 변경 내용이 인식되지 않으므로 표시 변경 RecyclerView 이 발생하지 않습니다.

RecyclerView 데이터 원본이 변경된 후에도 계속 업데이트하려면 변경된 컬렉션의 각 항목에 대해 어댑터의 NotifyItemChanged 메서드를 호출하도록 Random Pick 클릭 처리기를 수정해야 합니다(이 경우 첫 번째 사진과 교환된 사진의 두 항목이 변경됨). 이렇게 하면 RecyclerView 데이터 원본의 새 상태와 일치하도록 디스플레이가 업데이트됩니다.

Button randomPickBtn = FindViewById<Button>(Resource.Id.randPickButton);

randomPickBtn.Click += delegate
{
    if (mPhotoAlbum != null)
    {
        int idx = mPhotoAlbum.RandomSwap();

        // First photo has changed:
        mAdapter.NotifyItemChanged(0);

        // Swapped photo has changed:
        mAdapter.NotifyItemChanged(idx);
    }
};

이제 임의 선택 단추를 탭 RecyclerView 하면 디스플레이를 업데이트하여 컬렉션에서 더 아래로 내려온 사진이 컬렉션의 첫 번째 사진과 교환되었음을 표시합니다.

First screenshot before swap, second screenshot after swap

물론 NotifyDataSetChanged 두 개의 호출 NotifyItemChanged을 수행하는 대신 호출될 수 있지만 이렇게 하면 컬렉션의 두 항목만 변경되었더라도 전체 컬렉션을 새로 고쳐야 RecyclerView 합니다. 호출은 호출 NotifyItemChangedNotifyDataSetChanged보다 훨씬 더 효율적입니다.