ExpandableListView Example?

I am trying to understand how to implement the ExpandableListView in my MonoDroid app. I can't find any examples or tutorials anywhere on this site or thru google. Could anyone point me in the right direction?

Thanks.

Posts

  • StevaSteva RSMember ✭✭✭

    Here is example of custom expandable listview adapter:

    public class ExpandableListAdapter : BaseExpandableListAdapter
    {
        private readonly Context _context;
    
        public ExpandableListAdapter(Context context)
        {
            _context = context;
        }
    
        public override Object GetChild(int groupPosition, int childPosition)
        {
            return null;
        }
    
        public override long GetChildId(int groupPosition, int childPosition)
        {
            return childPosition;
        }
    
        public override int GetChildrenCount(int groupPosition)
        {
            return /*return child count for parent in groupPosition position*/;
        }
    
        public override View GetChildView(int groupPosition, int childPosition, bool isLastChild, View convertView, ViewGroup parent)
        {
            var view = convertView;
    
            if (view == null)
            {
                var inflater = _context.GetSystemService(Context.LayoutInflaterService) as LayoutInflater;
                view = inflater.Inflate(Resource.Layout.your_childview, null);
            }
    
            //setup childview
    
            return view;
        }
    
        public override Object GetGroup(int groupPosition)
        {
            return null;
        }
    
        public override long GetGroupId(int groupPosition)
        {
            return groupPosition;
        }
    
        public override View GetGroupView(int groupPosition, bool isExpanded, View convertView, ViewGroup parent)
        {
            var view = convertView;
    
            if (view == null)
            {
                var inflater = _context.GetSystemService(Context.LayoutInflaterService) as LayoutInflater;
                view = inflater.Inflate(Resource.Layout.your_groupview, null);
            }
    
            //setup groupview
    
            return view;
        }
    
        public override bool IsChildSelectable(int groupPosition, int childPosition)
        {
            return true;
        }
    
        public override int GroupCount
        {
            get { return Dal.Dal.DataAccesser.Schedules.Count; }
        }
    
        public override bool HasStableIds
        {
            get { return true; }
        }
    }
    

    Only thing left is to make layouts for group and child items and you are good to go.

  • ranirani INMember

    I am new to xamarin studio.How to use expandablelistview.I am trying to understand expandable list view.Please give me full example of expandable listview with all layout file.
    Thanks

  • DarrellBookerDarrellBooker USMember ✭✭

    @AndrewWay thanks for sharing. help me out a ton!

  • DarrellBookerDarrellBooker USMember ✭✭

    @AndrewWay how and where can I handle clicking of the child view?

  • DarrellBookerDarrellBooker USMember ✭✭

    nevermind i figured it out

  • AndrewWayAndrewWay USXamarin Team Xamurai
    edited March 2014

    @DarrellBooker‌ please share your approach - did you add a

    listView.ChildClick handler?

    listView.ChildClick += (object sender, ExpandableListView.ChildClickEventArgs e) => { Console.WriteLine("{0}:{1} clicked", e.GroupPosition, e.ChildPosition); };

  • DarrellBookerDarrellBooker USMember ✭✭

    @AndrewWay‌ I sure did. thanks again!

  • HarshadcseHarshadcse USMember ✭✭✭

    @AndrewWay‌ Superup example. thanks for sharing.

  • SanjayDevSanjayDev INMember

    @AndrewWay‌ thanks it helps.

  • BFipsBFips PTMember

    @AndrewWay‌

    I have an ExpandableListView and everything is working fine... except that sometimes items in the list view get mixed up.
    For example, when I try to delete an item, two or more get deleted too.

    I found out that I can prevent that from happening if I DO NOT reuse views in the GetChildView function.

    Resuming, I have two questions:

    1- Do you have any idea why this happens?

    2- I know views should be reused when possible, so is it a very bad approach, to disable child views reuse, or the impacts of that are not that bad?

    Thank you.

  • AndrewWayAndrewWay USXamarin Team Xamurai

    @BFips‌

    Sounds like you possibly are deleting elements from your model inappropriately - which is then causing more than one element getting deleted.

    You should definitely reuse as you will suffer a large performance hit when you constantly create new child views.

    Refer to this blogpost for more tips & tricks for optimizing your listview:

    http://blog.xamarin.com/creating-highly-performant-smooth-scrolling-android-listviews/

    again, the deleting of multiple items suggests that the way you're referencing your children items could be buggy.

  • ClockWiseClockWise USMember

    @AndrewWay

    I have the same issue as @BFips. Though I have an expandableListView with items that are not correctly updated without always creating the view in GetChildView. You seem to have a good understanding of Adapter (I've never used them before) so could you take a look here maybe? http://forums.xamarin.com/discussion/23787/expandablelistview-switching-between-different-layouts-always-inflate-view#latest

    Sorry for hijacking the thread, but I have the same topic and it's easier to just link to my description rather than writing it all here again.

  • BFipsBFips PTMember

    @AndrewWay‌

    Thank you for your reply.

    I followed your reference and create a ViewHolder as in the example as a way of optimizing the listview.
    However I'm still with the same problem of "needing" not to reuse views.

    What I display in each Child view is different properties from the same object in the respective parent view. Can somehow this be the problem?
    Also, this makes every parent only having one child. Does not reusing views in the GetChildView function still make any difference (as there´s only one child for each parent)?

  • AndrewWayAndrewWay USXamarin Team Xamurai

    @BFips best to paste your code then.

  • BFipsBFips PTMember

    @AndrewWay‌

    public class ItemListAdapter : BaseExpandableListAdapter
        {
            protected Activity context = null;
            protected IList<PwdItem> items = new List<PwdItem> ();
    
            public ItemListAdapter (Activity context, IList<PwdItem> items) : base ()
            {
                this.context = context;
                this.items = items;
            }    
    public override View GetGroupView (int position, bool isExpandable, View convertView, ViewGroup parent)
            {
                MyViewHolder holder = null;
                var view = convertView;
    
                if (view != null)
                    holder = view.Tag as MyViewHolder;
    
                if (holder == null) {
                    view = context.LayoutInflater.Inflate (Resource.Layout.Service, null);
                    holder = new MyViewHolder ();
                    holder.Service = view.FindViewById<TextView> (Resource.Id.serviceName);
                }
                var item = items [position];
    
                holder.Service.Text = item.Service;
    
                return view;
            }
    
            public override View GetChildView (int groupPosition, int childPosition, bool isLastChild, View convertView, ViewGroup parent)
            {
                MyViewHolder holder = null;
                var view = convertView;
                if (view != null) 
                    {
                    view = context.LayoutInflater.Inflate (Resource.Layout.PwdItem, null);
                    holder = view.Tag as MyViewHolder;
                }
                if (holder == null) 
                {
                    view = context.LayoutInflater.Inflate (Resource.Layout.PwdItem, null);
                    holder = new MyViewHolder ();
                    holder.LoginView = view.FindViewById<TextView> (Resource.Id.loginView);
                    holder.TextPassword = view.FindViewById<TextView> (Resource.Id.pwdView);
                    holder.CheckBox = view.FindViewById<CheckBox> (Resource.Id.checkBox);
                    holder.Delete = view.FindViewById<Button> (Resource.Id.deleteButton);
                    view.Tag = holder;
                }
    
                var item = items [groupPosition];
    
                holder.LoginView.Text = item.Text;
                holder.TextPassword.Text = item.Pwd;
                holder.CheckBox.Checked = item.Chk;
                holder.CheckBox.CheckedChange += delegate(object sender, CompoundButton.CheckedChangeEventArgs e) {
                    // not important stuff
                };
    
                holder.Delete.Click += (object sender, EventArgs e) => {
                    //Console.WriteLine (item.Service);
                    items.Remove (item);
                    TaskManager.Instance.RemoveItem (item);
                    this.NotifyDataSetChanged ();
                };
    
                return view;
            }
    

    I think the other functions are not important, but if you think so I will paste them as well.
    The PwdItem class is as follow:

    public class PwdItem
        {
            [PrimaryKey, AutoIncrement, Column ("_id")]
            public int Id { get; set; }
            public string Service { get; set; }
            public string Text { get; set; }
            public string Pwd { get; set; }
            public bool Chk { get; set; }
            public bool First { get; set; }
        }
    

    Thank you and let me know if you need anything else.

  • AndrewWayAndrewWay USXamarin Team Xamurai

    @BFips I'm confused why you have a single list for your Groups and Children

    Items[] is an array of all elements.

    are you intentionally deleting the group rather than the child - under holder.Delete.Click....

    items.Remove(items [groupPosition] )

    shouldn't this be items.Remove (items [childPosition])?

  • BFipsBFips PTMember

    @AndrewWay‌

    Yes it is intentionally. I only have an array of elements, and I'm displaying them in a list view. But I didn't want to show all the properties of each element. So in the parent view I only show the Service field, and if the user wants to see the rest, "opens" the expandable parent view to see the rest.

    On deleting, the item itself should be deleted, not only the child. As I said before, each parent will only have one child (being both the same item after all).

    I don´t know if it is a good way to do something like that, it makes sense to me.

    Thank you again, and I hope I was clear enough.

  • AndrewWayAndrewWay USXamarin Team Xamurai

    hmmm. not entirely sure, but i think you should create a regular listview rather than using an expandable listview.

    (still doesn't really address why a delete when reusing child views is causing the behavior you're seeing. )

    there is an expand/collapse animation that you should use instead.

    http://forums.xamarin.com/discussion/10406/expand-and-collapse-animation-of-a-layout-in-xamarin-studio

  • BFipsBFips PTMember

    Thank you for the reference @AndrewWay‌ , I will try that later or tomorrow.

  • BFipsBFips PTMember
    edited September 2014

    Hi @AndrewWay‌ I tried the expand and collapse animation and it worked, even with views reuse :)

    I still don't understand what was causing the delete item problem, but maybe this is a more correct way of doing what I wanted.

    Is there any way of having an arrow pointing up or down as the item is expanded or collapsed, like the ones in the expandable ListView? I mean, with Android Graphics and Animations.

    Thank you

  • Hi @AndrewWay‌ That was a nice example. Is it possible to use a expandable listview retrieving the data from sql server?
    Thanks

  • AndrewWayAndrewWay USXamarin Team Xamurai

    @EduardoSantana‌ Yes, it's possible to retrieve data from a SQLServer - but we recommend exposing your data via webservices. In any case - you can preload your data into an array - and then load the Expandable list view.

    please refer to this guide on using data from a DB in your app:
    http://developer.xamarin.com/guides/cross-platform/application_fundamentals/data/

  • @AndrewWay‌ Thanks for your help. Do you have de code to call the web service? Does it has to be a WCF? Thank you again.

  • DACopDACop USMember

    @AndrewWay Thank you very much.It was very helpful

  • RamarajRamaraj USMember

    @AndrewWay Thank you very much for post . Finally one thing how to write the longclick for child items

  • AlfredRoaAlfredRoa USMember

    Hi @AndrewWay,

    Your sample ExpandableListView project is very helpful. I made my own version by following your example. I have questions though with regards to showing a dialogFragment when specific ChildClick.

    I tried doing the following:

    expLV.ChildClick += (object sender, ExpandableListView.ChildClickEventArgs e) =>
    {
    Console.WriteLine(e.ChildPosition.ToString());
    }

    the event doesn't seem to get executed. I placed it right after I set the ExpandableListView.Adapter inside my activity class.

    Any help would be appreciated.

  • ConorMurphyConorMurphy USMember

    The Expandable example was very useful and saved me a lot of development time!

    Thanks! @AndrewWay

  • VivekKriplaniVivekKriplani INMember

    @AndrewWay How to add values in expandable list at run time from plain text?

  • AndrewWayAndrewWay USXamarin Team Xamurai

    @Vivek_K You would update the data object from your plain text file. So instead of statically defining the data. simply create a method to read in your file - after your app starts (preferably asynchronously)

  • VivekKriplaniVivekKriplani INMember

    @AndrewWay Can you help with example?

  • JaaqJaaq MXMember ✭✭

    any example?

  • Has anyone tried this one?

  • @AndrewWay: could it be that the sample is incomplete? If I try to debug (my way of learning how things really work), it bombs out at

    public override bool IsChildSelectable (int groupPosition, int childPosition)
    {
    throw new NotImplementedException ();
    }

    in the ExpandableListAdapter when I click on a section header.

  • AndrewWayAndrewWay USXamarin Team Xamurai

    @StephanSteiner what was the error?
    I haven't looked at the code in awhile, but it is intended to throw an exception - so maybe that's what you're running into?

  • AngelosNikolopoulosAngelosNikolopoulos USMember
    edited November 2016

    @AndrewWay how to change icon / hide the group indicator? And is it possible to use a selector xml like this:
    <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/arrowright" android:state_selected="false"/> <item android:drawable="@drawable/arrowdown" android:state_selected="true"/> <item android:drawable="@drawable/arrowright"/> </selector>

  • AndrewWayAndrewWay USXamarin Team Xamurai

    I believe it is possible - please refer to this post on stackoverflow:
    http://stackoverflow.com/questions/15501413/change-expandable-indicator-in-expandablelistview

  • @AndrewWay this worked beautifully.

    layout file:
    <ExpandableListView android:id="@+id/expandableListView" android:layout_width="fill_parent" android:layout_height="match_parent" android:background="#ffffff" android:groupIndicator="@drawable/group_indicator" />

    group_indicator.xml
    <?xml version="1.0" encoding="utf-8" ?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/arrow_down" android:state_empty="true"/> <item android:drawable="@drawable/arrow_right" android:state_expanded="true"/> <item android:drawable="@drawable/arrow_right"/> </selector>

    Main activity:
    expandableListView = FindViewById<ExpandableListView>(Resource.Id.expandableListView); var metrics = Resources.DisplayMetrics; int width = metrics.WidthPixels // get width form navigation drawer // int width = (int)Resources.GetDimension(Resource.Dimension.navdrawer_width); expandableListView.SetIndicatorBoundsRelative(width - GetPixelFromDips(50), width - GetPixelFromDips(10));

    public int GetPixelFromDips(float pixels) { float scale = Resources.DisplayMetrics.Density; return (int)(pixels * scale + 0.5f); }

Sign In or Register to comment.