Bar views list and rating in android xamarin

I have a list box, each item has a text view and a score bar. Layout element:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:minHeight="50dp"
    android:orientation="horizontal">
  <TextView
      android:id="@+id/name"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:lineSpacingExtra="3dp"
      android:paddingRight="10dp"
      android:paddingTop="5dp"
      android:textColor="#ffffff"
      android:textStyle="bold"
       android:textSize="15sp"
      android:typeface="sans"
       android:layout_alignParentRight="true"/>
  <RatingBar android:id="@+id/ratingbar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/name"

        android:numStars="5"
        android:stepSize="1.0"
             android:layout_alignParentLeft="true" />

</RelativeLayout>

      

this is the GetView method of my ListAdapter:

public override View GetView(int position, View convertView, ViewGroup parent)
        {
            View view = convertView;

            RatingBar rate; 

            if (view == null)
                view = context.LayoutInflater.Inflate(Resource.Layout.QuestionListViewItemLayout, parent, false);
               // view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItemActivated1, parent, false);

            question item = this[position];
            view.FindViewById<TextView>(Resource.Id.name).Text = item.text; 
            view.FindViewById<RatingBar>(Resource.Id.ratingbar).Rating = item.userrate;
            RatingBar rb = view.FindViewById<RatingBar>(Resource.Id.ratingbar);

            rb.RatingBarChange += (o, e) =>
            {
                item.userrate = System.Convert.ToInt32( e.Rating);
            };
            //view.FindViewById<TextView>(Resource.Id.SanadNumber).Text = item.sanadNumber.ToString();


            return view;
        }

      

on the line: "rb.RatingBarChange", when I change one of the rating bars in my list, some other elements change. that the delegate executes more than once every time I set a rating for one of my bars.

so when I read "item.userrate" which is edited by the rating bar there is no correct answer.

-1


source to share


2 answers


I want to have a list of Questions on my list. the question class looks like this:

public  class question
    {
        public int id { get; set; }
        public string text { get; set; }
        public int questionorder { get; set; }
        public int userrate { get; set; }

        public question()
        {
            userrate = 0;

        }

    }

      

now I need a QuestionListViewItemLayout.axml file to style my list:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:minHeight="50dp"
    android:orientation="horizontal">
  <TextView
      android:id="@+id/name"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:lineSpacingExtra="3dp"
      android:paddingRight="10dp"
      android:paddingTop="5dp"
      android:textColor="#ffffff"
      android:textStyle="bold"
       android:textSize="15sp"
      android:typeface="sans"now 
       android:layout_alignParentRight="true"/>
  <RatingBar android:id="@+id/ratingbar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/name"

        android:numStars="5"
        android:stepSize="1.0"
             android:layout_alignParentLeft="true" />

</RelativeLayout>

      

I now need a ListAdapter to manage the items in my list view, but first I need to create a Wrapper class to save the views:

 public class ViewWrapper : Java.Lang.Object
    {
        View base1;
        RatingBar rate = null;
        TextView label = null;

      public  ViewWrapper(View base1)
        {
            this.base1 = base1;
        }

      public  RatingBar getRatingBar()
        {
            if (rate == null)
            {
                rate = base1.FindViewById<RatingBar>(Resource.Id.ratingbar);
            }

            return (rate);
        }

       public TextView getLabel()
        {
            if (label == null)
            {
                label = base1.FindViewById<TextView>(Resource.Id.name);
            }

            return (label);
        }
    }

      



this class is only created for my question class and maybe you need to create your own wrapper similar to the previous code

time to create adapter class List:

public class QuestionListAdapter : BaseAdapter<question>
    {
        Activity context;
        List<question> list;
        public QuestionListAdapter(Activity _context, List<question> _list)
            : base()
        {
            this.context = _context;
            this.list = _list;
        }

        public override int Count
        {
            get { return list.Count; }
        }
        public override long GetItemId(int position)
        {
            return position;
        }
        public List<question> GetList()
        {
            return list;
        }
        public override question this[int index]
        {
            get { return list[index]; }
        }

        public override View GetView(int position, View convertView, ViewGroup parent)
        {
            View view = convertView;

            ViewWrapper wrapper;
            RatingBar rate;    

            question item = this[position];
            if (view == null)
            {
                view = context.LayoutInflater.Inflate(Resource.Layout.QuestionListViewItemLayout, parent, false);
                wrapper = new ViewWrapper(view);
                view.SetTag(Resource.Id.holder, wrapper);
                rate = wrapper.getRatingBar();

                rate.RatingBarChange += (o, e) =>
                {
                    RatingBar ratingBar = o as RatingBar;
                    int myPosition = (int)ratingBar.GetTag(Resource.Id.holder);
                    question model = list[myPosition];
                    model.userrate = System.Convert.ToInt32(e.Rating);
                };
            }
            else
            {

                wrapper = (ViewWrapper)view.GetTag(Resource.Id.holder);
                rate = wrapper.getRatingBar();

            }

            question model1 = list[position];

            wrapper.getLabel().Text = model1.text;
            rate.SetTag(Resource.Id.holder, position);
            rate.Rating = model1.userrate;

            return view;
        }

      

every time a view is created, I create a wrapper for it and put it in the viewport Section: [if (view == null)] and set an event to change the bar speed.

Another time when I load the views, I get the tag and set its rating.

+1


source


Each time GetView starts, you create a new event handler for the RatingBarChange event that creates a closure around the current question (item) instance (effectively keeping each item instance in memory and tied to each event handler instance). All of these event handlers will run every time and update every instance of the element with the same value.



Your RatingBarChange event should have one handler that receives the selected item and applies the rating.

0


source







All Articles