Forum Xamarin.Android

How to make two views clickable of RecycleView item (Xamarin.Android)?

I have to make a replica of the following RecyclerView:

The RecyclerView contains a list of Schedule objects. When I click on a star, I want to change its color. When I click on the text I want to open new Activity with more details about the Schedule.

In my activity I want to have the following methods:

//method which gets executed when I click on a star
OnStarClick()
{
    //Get Schedule id
    //Get reference of the star so I can change its color 
}

//method which gets executed when I click on a text
OnTextClicked()
{
    //Get Schedule id
}

Here is my activity:

public class SchedulesActivity : BaseActivity
{
    RecyclerView schedulesRecyclerView;
    RecyclerView.LayoutManager schedulesLayoutManager;
    SchedulesAdapter schedulesAdapter;

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

        SetContentView(Resource.Layout.SchedulesActivity);

        List<Schedule> schedules = //Get it from database
        schedulesRecyclerView = FindViewById<RecyclerView>(Resource.Id.schedulesRecyclerView);
        schedulesLayoutManager = new LinearLayoutManager(this);
        schedulesRecyclerView.SetLayoutManager(schedulesLayoutManager);
        schedulesAdapter = new SchedulesAdapter(schedules);
        schedulesRecyclerView.SetAdapter(schedulesAdapter);

    }

    OnStarClicked()
    {
    }

    OnTextClicked()
    {
    }

}

Here is the Schedule model:

public class Schedule
{
    public int Id { get; set; }
    public string Day { get; set; }
    public string Hour { get; set; }
    public string ShortDescription { get; set; }
    public string LongDescription { get; set; }
}

Here is my ViewHolder:

public class ScheduleViewHolder : RecyclerView.ViewHolder
{
    public ImageView starImageView { get; private set; }
    public TextView hourAndScheduleTextView { get; private set; }

    // Get references to the views defined in the CardView layout.
    public ScheduleViewHolder(View itemView)
        : base(itemView)
    {
        // Locate and cache view references:
        starImageView = itemView.FindViewById<ImageView>(Resource.Id.starImageView);
        hourAndScheduleTextView = itemView.FindViewById<TextView>(Resource.Id.hourAndScheduleTextView);
    }
}

Here is my adapter:

public class SchedulesAdapter : RecyclerView.Adapter
{
    public List<Schedule> listOfSchedules;

    public SchedulesAdapter(List<Schedule> schedules)
    {
        listOfSchedules = schedules;
    }

    public override int ItemCount
    {
        get { return listOfSchedules.Count; }
    }

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

        vh.hourAndScheduleTextView.Text = /*listOfSchedules[position].Hour + " " + */listOfSchedules[position].ShortDescription;
    }

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

        ScheduleViewHolder vh = new ScheduleViewHolder(itemView);
        return vh;
    }
}

Best Answer

  • jezhjezh Xamurai
    Accepted Answer

    I don't have the star icon , but I used a CheckBox to simulate this function.
    For CheckBox:

        public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
            {
                ScheduleViewHolder vh = holder as ScheduleViewHolder;
                Schedule item = listOfSchedules[position];
                vh.hourAndScheduleTextView.Text = /*listOfSchedules[position].Hour + " " + 
                 */listOfSchedules[position].ShortDescription;
    
                vh.MyCheckBox.SetOnCheckedChangeListener(null);
                vh.MyCheckBox.SetOnCheckedChangeListener(new MyListener(item));
                vh.MyCheckBox.Checked = item.isChecked;
    
            }
    

    For function method which gets executed when I click on a text, we just add a EventHandler in class SchedulesAdapter.

      public event EventHandler<int> ItemClick;
    

    Then the whole code is like this:

    ScheduleViewHolder.cs

     public class ScheduleViewHolder : RecyclerView.ViewHolder
        {
            public ImageView starImageView { get; private set; }
    
            public CheckBox MyCheckBox { get; set; }
            public bool IsChecked { get; set; }
    
            public TextView hourAndScheduleTextView { get; private set; }
    
            // Get references to the views defined in the CardView layout.
            public ScheduleViewHolder(View itemView, Action<int> listener)
                : base(itemView)
            {
                //starImageView = itemView.FindViewById<ImageView>(Resource.Id.item);
                MyCheckBox = itemView.FindViewById<CheckBox>(Resource.Id.myCheckBox);
                hourAndScheduleTextView = itemView.FindViewById<TextView>(Resource.Id.hourAndScheduleTextView);
                itemView.Click += (sender, e) => listener(base.LayoutPosition);
    
                MyCheckBox.Click += delegate
                {
                    if (MyCheckBox.Checked)
                    {
                        Console.WriteLine("I can get the adapter position here {0}", AdapterPosition);
                        IsChecked = true;
                    }
                    else
                    {
                        Console.WriteLine("I can get the adapter position here {0}", AdapterPosition);
                        IsChecked = false;
                    }
                };
            }
        }
    

    Schedule.cs

    public  class Schedule
        {
            public int Id { get; set; }
            public string Day { get; set; }
            public string Hour { get; set; }
            public string ShortDescription { get; set; }
            public string LongDescription { get; set; }
    
            public bool isChecked { get; set; }
        }
    

    class SchedulesAdapter

     public  class SchedulesAdapter : RecyclerView.Adapter
        {
            public List<Schedule> listOfSchedules;
    
            public event EventHandler<int> ItemClick;
    
    
            public SchedulesAdapter(List<Schedule> schedules)
            {
                listOfSchedules = schedules;
            }
    
            public override int ItemCount {
                get { return listOfSchedules.Count; }
            }
    
            public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
            {
                ScheduleViewHolder vh = holder as ScheduleViewHolder;
    
                Schedule item = listOfSchedules[position];
    
                vh.hourAndScheduleTextView.Text = /*listOfSchedules[position].Hour + " " + */listOfSchedules[position].ShortDescription;
    
                vh.MyCheckBox.SetOnCheckedChangeListener(null);
                vh.MyCheckBox.SetOnCheckedChangeListener(new MyListener(item));
                vh.MyCheckBox.Checked = item.isChecked;
    
            }
    
            public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
            {
                View itemView = LayoutInflater.From(parent.Context).
                        Inflate(Resource.Layout.ScheduleCardView, parent, false);
    
                ScheduleViewHolder vh = new ScheduleViewHolder(itemView,OnClick);
                return vh;
            }
    
            // Raise an event when the item-click takes place:
            void OnClick(int position)
            {
                if (ItemClick != null)
                    ItemClick(this, position);
            }
        }
    
        class MyListener : Java.Lang.Object, CompoundButton.IOnCheckedChangeListener
        {
            Schedule schedule;
    
            public MyListener(Schedule item)
            {
                this.schedule = item;
            }
    
            public void OnCheckedChanged(CompoundButton buttonView, bool isChecked)
            {
                schedule.isChecked = isChecked;
            }
        }
    

    class MainActivity

     public class MainActivity : AppCompatActivity
        {
    
            RecyclerView schedulesRecyclerView;
            RecyclerView.LayoutManager schedulesLayoutManager;
            SchedulesAdapter schedulesAdapter;
    
            List<Schedule> schedules;
    
            protected override void OnCreate(Bundle savedInstanceState)
            {
                base.OnCreate(savedInstanceState);
                Xamarin.Essentials.Platform.Init(this, savedInstanceState);
                // Set our view from the "main" layout resource
                SetContentView(Resource.Layout.activity_main);
    
                schedules = new List<Schedule>();
    
                schedules.Add(new Schedule { ShortDescription ="test1"});
                schedules.Add(new Schedule { ShortDescription = "test2" });
                schedules.Add(new Schedule { ShortDescription = "test3" });
                schedules.Add(new Schedule { ShortDescription = "test4" });
                schedules.Add(new Schedule { ShortDescription = "test5" });
                schedules.Add(new Schedule { ShortDescription = "test6" });
    
                schedulesRecyclerView = FindViewById<RecyclerView>(Resource.Id.schedulesRecyclerView);
                schedulesLayoutManager = new LinearLayoutManager(this);
                schedulesRecyclerView.SetLayoutManager(schedulesLayoutManager);
                schedulesAdapter = new SchedulesAdapter(schedules);
                schedulesRecyclerView.SetAdapter(schedulesAdapter);
    
                schedulesAdapter.ItemClick += OnItemClick;
            }
    
            void OnItemClick(object sender, int position)
            {
                int photoNum = position + 1;
                Toast.MakeText(this, "This is photo number " + photoNum, ToastLength.Short).Show();
            }
        }
    

    The result is:

Answers

  • jezhjezh Member, Xamarin Team Xamurai
    Accepted Answer

    I don't have the star icon , but I used a CheckBox to simulate this function.
    For CheckBox:

        public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
            {
                ScheduleViewHolder vh = holder as ScheduleViewHolder;
                Schedule item = listOfSchedules[position];
                vh.hourAndScheduleTextView.Text = /*listOfSchedules[position].Hour + " " + 
                 */listOfSchedules[position].ShortDescription;
    
                vh.MyCheckBox.SetOnCheckedChangeListener(null);
                vh.MyCheckBox.SetOnCheckedChangeListener(new MyListener(item));
                vh.MyCheckBox.Checked = item.isChecked;
    
            }
    

    For function method which gets executed when I click on a text, we just add a EventHandler in class SchedulesAdapter.

      public event EventHandler<int> ItemClick;
    

    Then the whole code is like this:

    ScheduleViewHolder.cs

     public class ScheduleViewHolder : RecyclerView.ViewHolder
        {
            public ImageView starImageView { get; private set; }
    
            public CheckBox MyCheckBox { get; set; }
            public bool IsChecked { get; set; }
    
            public TextView hourAndScheduleTextView { get; private set; }
    
            // Get references to the views defined in the CardView layout.
            public ScheduleViewHolder(View itemView, Action<int> listener)
                : base(itemView)
            {
                //starImageView = itemView.FindViewById<ImageView>(Resource.Id.item);
                MyCheckBox = itemView.FindViewById<CheckBox>(Resource.Id.myCheckBox);
                hourAndScheduleTextView = itemView.FindViewById<TextView>(Resource.Id.hourAndScheduleTextView);
                itemView.Click += (sender, e) => listener(base.LayoutPosition);
    
                MyCheckBox.Click += delegate
                {
                    if (MyCheckBox.Checked)
                    {
                        Console.WriteLine("I can get the adapter position here {0}", AdapterPosition);
                        IsChecked = true;
                    }
                    else
                    {
                        Console.WriteLine("I can get the adapter position here {0}", AdapterPosition);
                        IsChecked = false;
                    }
                };
            }
        }
    

    Schedule.cs

    public  class Schedule
        {
            public int Id { get; set; }
            public string Day { get; set; }
            public string Hour { get; set; }
            public string ShortDescription { get; set; }
            public string LongDescription { get; set; }
    
            public bool isChecked { get; set; }
        }
    

    class SchedulesAdapter

     public  class SchedulesAdapter : RecyclerView.Adapter
        {
            public List<Schedule> listOfSchedules;
    
            public event EventHandler<int> ItemClick;
    
    
            public SchedulesAdapter(List<Schedule> schedules)
            {
                listOfSchedules = schedules;
            }
    
            public override int ItemCount {
                get { return listOfSchedules.Count; }
            }
    
            public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
            {
                ScheduleViewHolder vh = holder as ScheduleViewHolder;
    
                Schedule item = listOfSchedules[position];
    
                vh.hourAndScheduleTextView.Text = /*listOfSchedules[position].Hour + " " + */listOfSchedules[position].ShortDescription;
    
                vh.MyCheckBox.SetOnCheckedChangeListener(null);
                vh.MyCheckBox.SetOnCheckedChangeListener(new MyListener(item));
                vh.MyCheckBox.Checked = item.isChecked;
    
            }
    
            public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
            {
                View itemView = LayoutInflater.From(parent.Context).
                        Inflate(Resource.Layout.ScheduleCardView, parent, false);
    
                ScheduleViewHolder vh = new ScheduleViewHolder(itemView,OnClick);
                return vh;
            }
    
            // Raise an event when the item-click takes place:
            void OnClick(int position)
            {
                if (ItemClick != null)
                    ItemClick(this, position);
            }
        }
    
        class MyListener : Java.Lang.Object, CompoundButton.IOnCheckedChangeListener
        {
            Schedule schedule;
    
            public MyListener(Schedule item)
            {
                this.schedule = item;
            }
    
            public void OnCheckedChanged(CompoundButton buttonView, bool isChecked)
            {
                schedule.isChecked = isChecked;
            }
        }
    

    class MainActivity

     public class MainActivity : AppCompatActivity
        {
    
            RecyclerView schedulesRecyclerView;
            RecyclerView.LayoutManager schedulesLayoutManager;
            SchedulesAdapter schedulesAdapter;
    
            List<Schedule> schedules;
    
            protected override void OnCreate(Bundle savedInstanceState)
            {
                base.OnCreate(savedInstanceState);
                Xamarin.Essentials.Platform.Init(this, savedInstanceState);
                // Set our view from the "main" layout resource
                SetContentView(Resource.Layout.activity_main);
    
                schedules = new List<Schedule>();
    
                schedules.Add(new Schedule { ShortDescription ="test1"});
                schedules.Add(new Schedule { ShortDescription = "test2" });
                schedules.Add(new Schedule { ShortDescription = "test3" });
                schedules.Add(new Schedule { ShortDescription = "test4" });
                schedules.Add(new Schedule { ShortDescription = "test5" });
                schedules.Add(new Schedule { ShortDescription = "test6" });
    
                schedulesRecyclerView = FindViewById<RecyclerView>(Resource.Id.schedulesRecyclerView);
                schedulesLayoutManager = new LinearLayoutManager(this);
                schedulesRecyclerView.SetLayoutManager(schedulesLayoutManager);
                schedulesAdapter = new SchedulesAdapter(schedules);
                schedulesRecyclerView.SetAdapter(schedulesAdapter);
    
                schedulesAdapter.ItemClick += OnItemClick;
            }
    
            void OnItemClick(object sender, int position)
            {
                int photoNum = position + 1;
                Toast.MakeText(this, "This is photo number " + photoNum, ToastLength.Short).Show();
            }
        }
    

    The result is:

  • jezhjezh Member, Xamarin Team Xamurai

    @SvetoslavHlebarov Have you resolved your question?

Sign In or Register to comment.