How to change background color of selected item in a listview on xamarin form?

TathagataBasuTathagataBasu INMember ✭✭
edited December 2016 in Xamarin.Forms

Hello,

I have ListView like this

     <StackLayout Spacing="0">
        <ListView x:Name="lvMenu" SeparatorColor="Green">
          <ListView.ItemTemplate>
            <DataTemplate>
              <ViewCell>
                <StackLayout Padding="10">
                  <Label HorizontalOptions="FillAndExpand" VerticalOptions="Center" Text="{Binding Title}" TextColor="#03a9f4" />
                </StackLayout>
              </ViewCell>
            </DataTemplate>
          </ListView.ItemTemplate>
        </ListView>
      </StackLayout>

Also have ItemSelected event handler like this

    lvMenu.ItemSelected += GotoPage;
    private void GotoPage(object sender, SelectedItemChangedEventArgs e)
    {
        var item = e.SelectedItem as MasterPageItem;
        if (item != null)
        {
            //Change bg
            if (item.Title == "Logout")
            {
                LogoutUser();
            }
            else
            {
                NavigationPage nPage = new NavigationPage((Page)Activator.CreateInstance(item.TargetType)) {
                    Title = item.Title
                };
                this.Detail = nPage;
                this.IsPresented = false;
            }
        }
    }
    public class MasterPageItem
    {
        public string Title { get; set; }
        public Type TargetType { get; set; }
    }

Can anyone suggest how to change the selected item's default background color?

Best Answer

Answers

  • TathagataBasuTathagataBasu INMember ✭✭

    Hello Namyslaw,
    Thanks for your quick answer, but I am looking for generic solution, not a platform specific solution or renderer. Can you please provide any solution in portable code?

  • TathagataBasuTathagataBasu INMember ✭✭
    edited December 2016

    Thanks @Mounika.Kola for the solution, works perfectly :smile:

    Btw, I need to reset the background color if another item is selected from that list. Any quick solution?

  • Mounika.KolaMounika.Kola USMember ✭✭✭

    Okay can you share any screenshot for better understanding.

  • TathagataBasuTathagataBasu INMember ✭✭
    edited December 2016

    @Mounika.Kola said:
    Okay can you share any screenshot for better understanding.

    Please check this @Mounika.Kola

  • Mounika.KolaMounika.Kola USMember ✭✭✭

    Try this once

     private void GotoPage(object sender, SelectedItemChangedEventArgs e)
     {
         var item = e.SelectedItem as MasterPageItem;
         youListViewName.GetChildAt( e.Position).SetBackgroundColor( Color.Red); 
     };
    
  • TathagataBasuTathagataBasu INMember ✭✭

    @Mounika.Kola said:
    Try this once

     private void GotoPage(object sender, SelectedItemChangedEventArgs e)
     {
         var item = e.SelectedItem as MasterPageItem;
         youListViewName.GetChildAt( e.Position).SetBackgroundColor( Color.Red); 
     };
    

    Hi @Mounika.Kola ,

    Got this error --
    'ListView' does not contain a definition for 'GetChildAt'....

    Can you share your skype please?

  • Mounika.KolaMounika.Kola USMember ✭✭✭
  • Mounika.KolaMounika.Kola USMember ✭✭✭

    @TathagataBasu

    Below sample is solution for your issue. Try once

  • TathagataBasuTathagataBasu INMember ✭✭

    Hi @Mounika.Kola ,

    Thanks for your great help. :smile:
    Everything are in place now.

  • Mounika.KolaMounika.Kola USMember ✭✭✭

    Well :smile:

  • Mounika.KolaMounika.Kola USMember ✭✭✭

    @TathagataBasu why don't you try like this ! Add TapGestureRecognizer for label rather than item selected event..

     <Label HorizontalOptions="FillAndExpand" VerticalOptions="Center" Text="{Binding Title}" TextColor="#03a9f4">
        <Label.GestureRecognizers>
             <TapGestureRecognizer Tapped="OnLabelClicked"/>
         </Label.GestureRecognizers>
     </Label>
    

    in .cs file

       private async void OnLabelClicked(object sender, EventArgs e)
       {
            try
            {
    
                var entity =((Label)sender);
                entity.BackgroundColor = yourcolor;
                var item = (MasterPageItem) entity.BindingContext;
                .........
            }
       } 
    

    or else Bind background color for label by your condition.In my sample I done by setting color for label.

  • Mounika.KolaMounika.Kola USMember ✭✭✭

    @TathagataBasu why don't you try like this ! Add TapGestureRecognizer for label rather than item selected event..

     <Label HorizontalOptions="FillAndExpand" VerticalOptions="Center" Text="{Binding Title}" TextColor="#03a9f4">
        <Label.GestureRecognizers>
             <TapGestureRecognizer Tapped="OnLabelClicked"/>
         </Label.GestureRecognizers>
     </Label>
    

    in .cs file

       private async void OnLabelClicked(object sender, EventArgs e)
       {
            try
            {
    
                var entity =((Label)sender);
                entity.BackgroundColor = yourcolor;
                var item = (MasterPageItem) entity.BindingContext;
                .........
            }
       } 
    

    or else Bind background color for label by your condition.In my sample I done by setting color for label.

  • GabeArcherGabeArcher USMember

    @NamyslawSzymaniuk said:
    My solution are custom renderers.

    Thank you, it was really useful. If someone knows the native environments it is the best way, I think.

  • pratiuskumardubeypratiuskumardubey USMember ✭✭

    Thanks @Mounika.Kola

    That is perfect clue.

  • Mounika.KolaMounika.Kola USMember ✭✭✭
  • DaveUDaveU GBMember ✭✭

    @NamyslawSzymaniuk Thank you very much for the full width separator iOS code ;)

  • darkeagledarkeagle USMember

    @NamyslawSzymaniuk said:
    My solution are custom renderers.
    Android:

    using Android.Content;
    using Android.Views;
    using MyApp.Droid.Renderers;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.Android;
    using View = Android.Views.View;
    
    [assembly: ExportRenderer(typeof(ViewCell), typeof(ViewCellTransparent))]
    namespace MyApp.Droid.Renderers
    {
        public class ViewCellTransparent : ViewCellRenderer
        {
            protected override View GetCellCore(Cell item, View convertView, ViewGroup parent, Context context)
            {
                var cell = base.GetCellCore(item, convertView, parent, context);
                var listView = parent as Android.Widget.ListView;
    
                if (listView != null)
                {
                    // Disable native cell selection color style - set as *Transparent*
                    listView.SetSelector(Android.Resource.Color.Transparent);
                    listView.CacheColorHint = Android.Graphics.Color.Transparent;
                }
    
                return cell;
            }
        }
    }
    

    IOS:

    using MyApp.iOS.Renderers;
    using UIKit;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.iOS;
    
    [assembly: ExportRenderer(typeof(ViewCell), typeof(ViewCellTransparent))]
    namespace MyApp.iOS.Renderers
    {
        public class ViewCellTransparent : ViewCellRenderer
        {
            public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
            {
                var cell = base.GetCell(item, reusableCell, tv);
                if (cell != null)
                {
                    // Disable native cell selection color style - set as *Transparent*
                    cell.SelectionStyle = UITableViewCellSelectionStyle.None;
                }
                return cell;
            }
        }
    }
    

    BTW - full width separator, at iOS, as by OOTB it's not full width:

    using MyApp.iOS.Renderers;
    using UIKit;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.iOS;
    
    [assembly: ExportRenderer(typeof(ListView), typeof(ListViewSeparated))]
    namespace MyApp.iOS.Renderers
    {
        public class ListViewSeparated : ListViewRenderer
        {
            protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
            {
                base.OnElementChanged(e);
    
                if (Control == null) return;
    
                // ListView Separator for whole view width
                Control.SeparatorInset = UIEdgeInsets.Zero;
                Control.LayoutMargins = UIEdgeInsets.Zero;
                Control.CellLayoutMarginsFollowReadableWidth = false;
    
                // ListView Separator - remove it, from empty cells
                Control.TableFooterView = new UIView();
            }
        }
    }
    

    I think your solution is very good!

    Do you know how to implement CachingStrategy=RecycleElements in a custom ListView?

  • BhargavkumarBhargavkumar USMember

    Thanks @Mounika.Kola
    Your solution is very simple and working like charm

  • SheemuSheemu USMember ✭✭

    Thanks @Mounika.Kola but its solution are not working properly with StackLayout because we are not changeing StackLayout Previous background color.

    public class MenuCell : ViewCell
    {
    public string Text
    {
    get { return label.Text; }
    set { label.Text = value; }
    }
    Label label;

        public ImageSource ImageSrc
        {
            get { return image.Source; }
            set { image.Source = value; }
        }
        Image image;
         StackLayout sLayout;
        StackLayout _previousSLayout;
        public MenuPage Host { get; set; }
    
        public MenuCell()
        {
            image = new Image
            {
                HeightRequest = 20,
                WidthRequest = 20,
            };
    
            image.Opacity = 0.5;
            image.SetBinding(Image.SourceProperty, ImageSrc);
    
            label = new Label
            {
    
                VerticalTextAlignment = TextAlignment.Center,
                TextColor = Color.Gray,
            };
    
    
            sLayout = new StackLayout
            {
                BackgroundColor = Color.White,
    
                Padding = new Thickness(20, 0, 0, 0),
                Orientation = StackOrientation.Horizontal,
                Spacing = 20,
                Children = { image, label }
            };
    
            View = sLayout;
    
    
    
        }
    
        protected override void OnTapped()
        {
            base.OnTapped();
    
            Host.Selected(label.Text);
            sLayout.BackgroundColor = Color.Red;
        }
    }  
    
  • Mounika, how can I change the background color of a line in ListView when clicking a image with TagGestureRecogniser?
    Best Regards,
    Pedro

Sign In or Register to comment.