Custom Adapter in Xamarin Android

I need Help please

I have custom adapter for list view include button my problem i need this button hide when i click but when set button to invisible some button on other item that i don't click hide .

this my code :

public void OnClick(View v)
{
string name = (string)v.Tag;

v.Visibility = ViewStates.Invisible; string text = string.Format("{0} Button Click.", name);

Toast.MakeText(this.activity, text, ToastLength.Short).Show();

and i attach image show result when i click on button .

Posts

  • ErikHa.5803ErikHa.5803 VNMember ✭✭

    Where is OnClick(View v) attached to ?

  • ibrahimdahanibrahimdahan USMember ✭✭

    @ErikHa.5803

    this my code :

    public class ButtonActivity : ListActivity
    {

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
    
            List<Player> players = Player.GetPlayers();
            this.ListAdapter = new ButtonAdapter(this, players);
        }
    
        protected override void OnListItemClick(ListView l, View v, int position, long id)
        {
            base.OnListItemClick(l, v, position, id);
    
            Player player = ((ButtonAdapter)this.ListAdapter)[position];
            string text = string.Format("{0} Item Click!", player.Name);
            Toast.MakeText(this, text, ToastLength.Short).Show();
        }
    
        private class ButtonAdapter : BaseAdapter<Player>
        {
            private Activity activity;
            private List<Player> data;
    
            public ButtonAdapter(Activity activity, List<Player> data)
            {
                this.activity = activity;
                this.data = data;
            }
    
            public override Player this[int position]
            {
                get { return this.data[position]; }
            }
    
            public override int Count
            {
                get { return this.data.Count(); }
            }
    
            public override long GetItemId(int position)
            {
                return 0;
            }
    
            public override View GetView(int position, View convertView, ViewGroup parent)
            {
                View view = convertView;
    
                if (view == null)
                {
                    view = this.activity.LayoutInflater.Inflate(Resource.Layout.PlayerListItem3, null);
                }
    
                Player player = this.data[position];
    
                string name = player.Name;
    
                if (player.Captain)
                {
                    name = string.Format("{0} (c)", name);
                }
    
                view.FindViewById<TextView>(Resource.Id.txtName).Text = name;
                view.FindViewById<TextView>(Resource.Id.txtTeam).Text = player.Team;
    
                Button  button1 = view.FindViewById<Button>(Resource.Id.button1);
                button1.Tag = name;
                button1.SetOnClickListener(new ButtonClickListener(this.activity));
    
                return view;
            }
    
            private class ButtonClickListener : Java.Lang.Object, View.IOnClickListener
            {
                private Activity activity;
    
                public ButtonClickListener(Activity activity)
                {
                    this.activity = activity;
    
    
    
                }
    
                public void OnClick(View v)
                {
                    string name = (string)v.Tag;
    
                    v.Visibility = ViewStates.Invisible;
                    string text = string.Format("{0} Button Click.", name);
    
                    Toast.MakeText(this.activity, text, ToastLength.Short).Show();
                }
            }
        }
    }
    
  • ErikHa.5803ErikHa.5803 VNMember ✭✭

    Well, there are 2 points in your code I would change:
    1. In your custom adapter ButtonAdapter,
    method
    long GetItemId(int position)

    should return a unique id to reflect different Item. Hence

        public override long GetItemId(int position)
        {
            return position;
        }
    
    1. You should really implement Events - a powerful feature in C# which provides alternative to SetOnClickListener in Java

    An illustration of this new approach is:

        public override View GetView(int position, View convertView, ViewGroup parent)
        {
            View view = convertView;
    
            if (view == null)
            {
                view = this.activity.LayoutInflater.Inflate(Resource.Layout.PlayerListItem3, null);
            }
    
            Player player = this.data[position];
    
            string name = player.Name;
    
            if (player.Captain)
            {
                name = string.Format("{0} (c)", name);
            }
    
            view.FindViewById<TextView>(Resource.Id.txtName).Text = name;
            view.FindViewById<TextView>(Resource.Id.txtTeam).Text = player.Team;
    
            Button  button1 = view.FindViewById<Button>(Resource.Id.button1);
            button1.Tag = name;
        button1.Click += (o, e) => 
            {
            Button button = (Button)e;
            buttVisibility = ViewStates.Invisible;le;
            }
    
            return view;
        }
    
  • ibrahimdahanibrahimdahan USMember ✭✭

    thank's @ErikHa.5803

    but when applay this code show my some error :smile:

  • ibrahimdahanibrahimdahan USMember ✭✭

    @ErikHa.5803 plase help my

  • ErikHa.5803ErikHa.5803 VNMember ✭✭
    edited October 2016

    Sorry for my late response.
    There was a mistake I made in the previous answer.
    It should be something like this

        button1.Click += (o, e) => 
        {
        Button button = (Button)o;
        button.Visibility = ViewStates.Invisible;
        };
    
  • Emixam23Emixam23 USMember ✭✭✭

    Hi dude,

    I appreciate that you mentioned me for help, however, I'm doing Xamarin Forms.. So I don't know about this kind of project :/

    With the modification of @ErikHa.5803, it still doesn't work? Because yeah (o, e) => {} is corresponding to (object sender, EventArgs ea) {}

  • ibrahimdahanibrahimdahan USMember ✭✭

    Thank you @Emixam23 , yes (object sender, EventArgs ea) {} not work .

  • Emixam23Emixam23 USMember ✭✭✭

    What? I use that for button events x)

    public async void WhenMyButtonIsClicked(object sender, EventArgs ea)
    {
        Debug.WriteLine("plop");
    }
    

    Then in xaml

    <Button Clicked="WhenMyButtonIsClicked"/>
    
  • rbmanian75rbmanian75 USMember ✭✭

    Hi,
    Please check this https://blog.xamarin.com/creating-highly-performant-smooth-scrolling-android-listviews.

    The wrong button hides because android reuses the view created before by passing it as convertview.

    So please set the button event handler only once for the first time ie when convertview is null

        if (convertView == null)
        {
                    button1.SetOnClickListener(new ButtonClickListener(this.activity));
        }
    

    Try this and it should work.

    I recommend you to use the viewholder pattern as explained in the article.

    Hope This Helps.

  • rbmanian75rbmanian75 USMember ✭✭

    Sorry i forgot the say one thing. You have to maintain state of the button visibility in the player object.

    For that add a property called buttonVisibility in player object and first set all the player objects with Visible.

    Do this in the getview

    Button button1 = view.FindViewById(Resource.Id.button1);
    button1.Tag = name;

    if (convertView == null)
    {
                button1.SetOnClickListener(new ButtonClickListener(this.activity));
    }
    

    button1.Visibility = player.buttonVisibility

    private class ButtonClickListener : Java.Lang.Object, View.IOnClickListener
    {
    private Activity activity;

            public ButtonClickListener(Activity activity)
            {
                this.activity = activity;
    
    
    
            }
    
            public void OnClick(View v)
            {
                string name = (string)v.Tag;
    
                v.Visibility = ViewStates.Invisible;
    

    // here you have to update player object buttonVisibility

    player.buttonVisibility = ViewStates.Invisible;

                string text = string.Format("{0} Button Click.", name);
    
                Toast.MakeText(this.activity, text, ToastLength.Short).Show();
            }
        }
    

    Hope this helps

  • AhmadAwadaAhmadAwada SAMember

    Hi Ibrahim this code should work for you

      public class HomeScreenAdapter : BaseAdapter<TableItem>
            {
                List<TableItem> items;
                Activity context;
                public HomeScreenAdapter(Activity context, List<TableItem> items)
                    : base()
                {
                    this.context = context;
                    this.items = items;
                }
                public override long GetItemId(int position)
                {
                    return position;
                }
                public override TableItem this[int position]
                {
                    get { return items[position]; }
                }
                public override int Count
                {
                    get { return items.Count; }
                }
                public override View GetView(int position, View convertView, ViewGroup parent)
                {
                    var item = items[position];
                    View view = convertView;
                    Button btn;
    
                    if (view == null)
                    {
                        view = context.LayoutInflater.Inflate(Resource.Layout.layoutitems, null);
                        btn = view.FindViewById<Button>(Resource.Id.button1);
    
                        btn.Click += (sender, args) =>
                        {                        
                            int pos = (int)btn.Tag;
                            Toast.MakeText(context,items[pos].Heading, ToastLength.Short).Show();
                            items[pos].Visible = false;
                            btn.Visibility = ViewStates.Invisible;                       
                        };
                    }// no view to re-use, create new
                     else
                        btn = view.FindViewById<Button>(Resource.Id.button1);
    
                    btn.Tag = position;
    
                    view.FindViewById<TextView>(Resource.Id.txtName).Text = item.Heading;
                    view.FindViewById<TextView>(Resource.Id.txtTeam).Text = item.Subheading;
                    if (item.Visible)
                        btn.Visibility = ViewStates.Visible;
                    else
                        btn.Visibility = ViewStates.Invisible;
                    //  });
    
                    return view;
    
                }
    
    
            }
            public class TableItem
            {
                public string Heading;
                public string Subheading;
                public bool Visible=true;
                public TableItem(string Heading, string Subheading)
                {
                    this.Heading = Heading;
                    this.Subheading = Subheading;
                }
            }
    
  • ibrahimdahanibrahimdahan USMember ✭✭

    yes yes this code work perfect

    @AhmadAwada You are a professional programmer
    thank you very very match for help my .......

  • LearnEverythingLearnEverything USMember ✭✭

    Reusable adapters of all kind of datamodels

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using Android.Content;
    using Android.Views;
    using Android.Widget;
    using Object = Java.Lang.Object;
    
    namespace XamarinAndroid.Basic.Core
    {
        public class CustomListAdapter<T> : BaseAdapter
        {
            private int LayoutInflaterId { get; }
            private readonly Context c;
            public ObservableCollection<T> Items { get; private set; }
            private LayoutInflater inflater;      
            public event EventHandler<CustomAdapterViewHolder> ItemViewTemplated;
            /*
             * CONSTRUCTOR
             */
            /// <summary>
            /// layoutInflaterId is like Resource.Layout.list_item
            /// </summary>
            /// <param name="c"></param>
            /// <param name="spacecrafts"></param>
            /// <param name="layoutInflaterId"></param>
            public CustomListAdapter(IEnumerable<T> items, int layoutInflaterId)
            {
                this.Items = new ObservableCollection<T>(items);
                this.LayoutInflaterId = layoutInflaterId;
                this.c = Android.App.Application.Context;
                this.Items.CollectionChanged += (sender, e) =>
                {               
                    this.NotifyDataSetChanged();
                };
            }
            /*
             * RETURN ITEMS
             */
            public override Object GetItem(int position)
            {
                var item = Items[position];
                return item as Object;
            }
            /*
             * ITEMS ID
             */
            public override long GetItemId(int position)
            {
                return position;
            }
            /*
             * RETURN INFLATED VIEW
             */
            public override View GetView(int position, View convertView, ViewGroup parent)
            {
                //INITIALIZE INFLATER
                if (inflater == null)
                {
                    inflater = (LayoutInflater)c.GetSystemService(Context.LayoutInflaterService);
                }
                //INFLATE OUR MODEL LAYOUT
                if (convertView == null)
                {
                    convertView = inflater.Inflate(LayoutInflaterId, parent, false);
                }
                //BIND DATA
                CustomAdapterViewHolder holder = new CustomAdapterViewHolder(convertView, position);           
                //convertView.SetBackgroundColor(Color.LightBlue);
                this.ItemViewTemplated?.Invoke(this, holder);
                return convertView;
            }
            /*
             * TOTAL NUM OF ITEMS
             */
            public override int Count
            {
                get { return Items.Count(); }
            }
    
            public void ReplaceItems(IEnumerable<T> newItems)
            {
                this.Items = new ObservableCollection<T>(newItems);
            }
        }
        /// <summary>
        ///Sample On TextView: Text = Model[ItemPosition].Name
        /// </summary>
        public class CustomAdapterViewHolder : Java.Lang.Object
        {
            //adapter views to re-use
            public View ItemView { get; }
            public int ItemPosition { get; }
            public CustomAdapterViewHolder(View itemView, int position)
            {
                this.ItemView = itemView;
                this.ItemPosition = position;
            }
        } 
    }
    

    assign event and draw ui

    adapter = new CustomListAdapter<WordModel>(new List<WordModel>(), Resource.Layout.list_item);
                this.searchView.QueryTextChange += (s, view) =>
                {
                    var list = DataLoader.Dictionary.SearchWordList(view.NewText, renderDefinition:true);
                    adapter = new CustomListAdapter<WordModel>(list, Resource.Layout.list_item);
                    adapter.ItemViewTemplated += (d, holder) =>
                    {
    
                        (holder.ItemView.FindViewById<TextView>(Resource.Id.wordTxt)).Text = adapter.Items[holder.ItemPosition].Word;
                        (holder.ItemView.FindViewById<TextView>(Resource.Id.definitionTxt)).Text = adapter.Items[holder.ItemPosition].Definition;
                    };
                    this.listView.Adapter = adapter;
                };
    
                this.searchView.QueryTextSubmit += (s, view) =>
                {
                      string query = view.NewText;
    
                };
    
Sign In or Register to comment.