Поиск…


Основы RecyclerView

Это пример использования Android Support Library V7 RecyclerView . Библиотеки поддержки обычно рекомендуются, поскольку они обеспечивают обратные совместимые версии новых функций, предоставляют полезные элементы пользовательского интерфейса, которые не входят в структуру, и предоставляют ряд утилит, которые приложения могут использовать.

Чтобы получить RecyclerView , мы установим необходимые пакеты Nuget. Сначала мы будем искать v7 recyclerview . Прокрутите вниз, пока мы не увидим Xamarin Android Support Library - v7 RecyclerView . Выберите его и нажмите « Добавить пакет» .

введите описание изображения здесь

В качестве альтернативы, Android Support Library V7 RecyclerView доступна как компонент Xamarin. Чтобы добавить компонент, щелкните правой кнопкой мыши « Components в проекте Android в обозревателе решений и нажмите « Get More Components .

введите описание изображения здесь

В появившемся окне «Магазин компонентов» найдите RecyclerView. В списке поиска выберите Android Support Library V7 RecyclerView . Затем нажмите « Add to App . Компонент добавляется в проект.

введите описание изображения здесь

Следующий шаг - добавить RecyclerView на страницу. В axml (layout) мы можем добавить RecyclerView как RecyclerView ниже.

<android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

RecyclerView требует, чтобы как минимум два вспомогательных класса были настроены для базовой стандартной реализации: Adapter и ViewHolder . Adapter раздувает макеты элементов и связывает данные с представлениями, отображаемыми в RecyclerView. ViewHolder просматривает и сохраняет ссылки на просмотр. Владелец просмотра также помогает при обнаружении кликов по элементам.

Вот базовый пример класса адаптера

public class MyAdapter : RecyclerView.Adapter
{
    string [] items;

    public MyAdapter (string [] data)
    {
        items = data;
    }

    // Create new views (invoked by the layout manager)
    public override RecyclerView.ViewHolder OnCreateViewHolder (ViewGroup parent, int viewType)
    {   
        // set the view's size, margins, paddings and layout parameters
        var tv = new TextView (parent.Context);
        tv.SetWidth (200);
        tv.Text = "";

        var vh = new MyViewHolder (tv);
        return vh;
    } 

    // Replace the contents of a view (invoked by the layout manager)
    public override void OnBindViewHolder (RecyclerView.ViewHolder viewHolder, int position)
    {
        var item = items [position];

        // Replace the contents of the view with that element
        var holder = viewHolder as MyViewHolder;
        holder.TextView.Text = items[position];
    }

    public override int ItemCount {
        get {
            return items.Length;
        }
    }
}

В методе OnCreateViewHolder мы сначала надуваем представление и создаем экземпляр класса ViewHolder. Этот экземпляр должен быть возвращен. Этот метод вызывается адаптером, когда требуется новый экземпляр ViewHolder. Этот метод не будет вызываться для каждой отдельной ячейки. Когда RecyclerView имеет достаточно ячеек для заполнения представления, он будет повторно использовать старые ячейки, которые прокручиваются из представления для дальнейших ячеек.

Для отображения данных в указанной позиции обратный вызов OnBindViewHolder вызывается адаптером. Этот метод должен обновлять содержимое itemView, чтобы отразить элемент в данной позиции.

Поскольку ячейка содержит только один TextView , мы можем иметь простой ViewHolder, как показано ниже.

public class MyViewHolder : RecyclerView.ViewHolder 
{
    public TextView TextView { get; set; }


    public MyViewHolder (TextView v) : base (v)
    {
        TextView = v;
    }
}

Следующий шаг - связать вещи с Activity .

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

    // Plug in the linear layout manager:
    var layoutManager = new LinearLayoutManager (this) { Orientation = LinearLayoutManager.Vertical };
    mRecyclerView.SetLayoutManager (layoutManager);
    mRecyclerView.HasFixedSize = true;

    var recyclerViewData = GetData();
    // Plug in my adapter:
    mAdapter = new MyAdapter (recyclerViewData);
    mRecyclerView.SetAdapter (mAdapter);
}

string[] GetData()
{ 
     string[] data;
     .
     .
     .
     return data;
}

Класс LayoutManager отвечает за измерение и позиционирование позиций элементов в RecyclerView, а также за определение политики для того, когда следует перерабатывать элементы, которые больше не видны пользователю. Перед RecyclerView нам пришлось использовать ListView для размещения ячеек, как в списке вертикальной прокрутки, так и в GridView для отображения элементов в двумерной прокручиваемой сетке. Но теперь мы можем добиться как с RecyclerView, установив другой LayoutManger. LinearLayoutManager упорядочивает ячейки, как в ListView, а GridLayoutManager упорядочивает ячейки сеткой.

RecyclerView с событиями Click

В этом примере показано, как установить Click EventHandlers в Xamarin.Android RecyclerView.

В Android Java для настройки прослушивателя нажмите кнопку onClickListener для просмотра, которое будет нажато, например:

ImageView picture = findViewById(R.id.item_picture);
picture.setOnClickListener(new View.OnClickListener() {
    public void onClick(View v) {
        // do stuff
    }
});

Однако в Xamarin.Android способ настроить слушателя для события Click - это добавить EventHandler следующими способами:

1.

ImageView picture = FindViewById<ImageView>(Resource.Id.item_picture);
picture.Click += delegate {
    // do stuff
};

2.

ImageView picture = FindViewById<ImageView>(Resource.Id.item_picture);
picture.Click += async delegate {
    // await DoAsyncMethod();
    // do async stuff
};

3.

ImageView picture = FindViewById<ImageView>(Resource.Id.item_picture);
picture.Click += Picture_Click;
... // rest of your method

private void Picture_Click(object sender, EventArgs e)
{
    // do stuff
}

Обратите внимание, что EventHandler добавляется, а не устанавливается. Если ClickTimeHandler добавлен внутри метода GetView из адаптера GridView / ListView или метода OnBindViewHolder из RecyclerView.Adapter, каждый раз при создании представления элемента будет добавлен новый EventHandler. После прокрутки несколько раз будет добавлено несколько EventHandlers, и при щелчке на экране все они будут запущены.

Чтобы избежать этой проблемы, EventHandlers должны быть отписаны и подписаны впоследствии в методах GetView или OnBindViewHolder. Кроме того, они должны использовать способ номер 3. для установки EventHandler, иначе невозможно отменить подписку на EventHandlers.

Пример события RecyclerView.Adapter with Click показан ниже:

public class ViewHolderPerson : Android.Support.V7.Widget.RecyclerView.ViewHolder
{
    public View Item { get; private set; }
    public ImageView Picture { get; private set; }
    public TextView Name { get; private set; }

    public ViewHolderPerson(View itemView) : base(itemView)
    {
        this.Item = itemView;
        this.Picture = itemView.FindViewById<ImageView>(Resource.Id.Item_Person_Picture);
        this.Name = itemView.FindViewById<TextView>(Resource.Id.Item_Person_Name);
    }
}

public class AdapterPersons : Android.Support.V7.Widget.RecyclerView.Adapter
{
    private Context context;
    private Android.Support.V7.Widget.RecyclerView recyclerView;
    private List<Person> persons;

    public AdapterPersons(Context context, Android.Support.V7.Widget.RecyclerView recyclerView, List<Person> persons)
    {
        this.context = context;
        this.recyclerView = recyclerView;
        this.persons = persons;
    }

    public override int ItemCount => persons.Count;

    public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
    {
        Person person = this.persons[position];
        ((ViewHolderPerson)holder).Name.Text = person.Name;
        ((ViewHolderPerson)holder).Picture.SetImageBitmap(person.Picture);

        // Unsubscribe and subscribe the method, to avoid setting multiple times.
        ((ViewHolderPerson)holder).Item.Click -= Person_Click;
        ((ViewHolderPerson)holder).Item.Click += Person_Click;
    }

    private void Person_Click(object sender, EventArgs e)
    {
        int position = this.recyclerView.GetChildAdapterPosition((View)sender);
        Person personClicked = this.persons[position];
        if(personClicked.Gender == Gender.Female)
        {
            Toast.MakeText(this.context, "The person clicked is a female!", ToastLength.Long).Show();
        }
        else if(personClicked.Gender == Gender.Male)
        {
            Toast.MakeText(this.context, "The person clicked is a male!", ToastLength.Long).Show();
        }
    }

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

}


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow