How I can disable highlight item in ListView?

I could not disable highlight item. I tried to use this code (I took it from forum):
listView.ItemTapped += (object sender, ItemTappedEventArgs e) => { if (e.Item == null) return; ((ListView)sender).SelectedItem = null; // de-select the row };
But if I click in the item then I can see blue highlight that will disabled after some time.

Best Answer

«1

Answers

  • I believe this is the only option at the moment. What is really missing is SelectionMode="None"

  • @JamesMontemagno
    Thanks, this solved my problem

  • @JamesMontemagno This didn't work for me!! any idea?

  • AdrianKnightAdrianKnight USMember ✭✭✭✭

    How does custom rendering work for ViewCell? I also need to disable highlighting.

  • voidvoid DKBeta ✭✭✭

    @JamesMontemagno

    Cant seem to make the cell.SelectionStyle = UITableViewCellSelectionStyle.None; work on Forms 2.0.1.6505.
    It used to work, but now it does not work anymore.

  • vikram.2579vikram.2579 INUniversity ✭✭

    Create a cell renderer and override the GetCell method. Now do the following,

    public override UITableViewCell GetCell (Cell item, UITableViewCell reusableCell, UITableView tv)
    {
        var cell = base.GetCell (item, reusableCell, tv);
        item.Tapped += (sender, e) =>
         {
           cell.SetSelected(false,false);
         };
    
  • nprokopicnprokopic RSMember ✭✭
    edited April 2016

    ListView/TableView iOS behaviour summary (in my case)

    This solution worked for TableView items:

    [assembly: ExportRenderer(typeof(ViewCell), typeof(NativeViewCellRenderer))]
    namespace MyApp.iOS.Renderers
    {
        public class NativeViewCellRenderer : ViewCellRenderer
        {
            public override UITableViewCell GetCell (Cell item, UITableViewCell reusableCell, UITableView tv)
            {
                var cell = base.GetCell(item, reusableCell, tv);
    
                // removes default selection style (gray background color on tapped event)
                cell.SelectionStyle = UITableViewCellSelectionStyle.None;
    
                return cell;
            }
        }
    }
    
    

    The solution above and none of the following didn't work for ListView items (item selection style was still there):

    // Xamarin Forms ListView ItemTapped event didn't work
    listView.ItemTapped += (object sender, ItemTappedEventArgs e) =>
    {
        if (e.Item == null) return;
        ((ListView)sender).SelectedItem = null; // de-select the row
    };
    
    // Cell Tapped event in renderer didn't work
    public override UITableViewCell GetCell (Cell item, UITableViewCell reusableCell, UITableView tv)
    {
        var cell = base.GetCell (item, reusableCell, tv);
    
        item.Tapped += (sender, e) =>
        {
            cell.SetSelected(false,false);
        };
    }
    
    

    The only solution that worked for me and that successfully removed selection style on ListView items (gray color on tap event):

    namespace MyApp.Views
    {
        // Extended Xamarin Forms ViewCell
        public partial class NativeViewCell : ViewCell
        {
            public NativeViewCell()
            {
                InitializeComponent();
    
                // Adds empty gesture recognizer
                // ViewCell content has a button where Click event works without issues
                View.GestureRecognizers.Clear();
                View.GestureRecognizers.Add(new TapGestureRecognizer());
            }
        }
    }
    

    Thanks to @JaekovSegovia for this last solution (empty gesture recognizer that solved the issue)!

  • LeeOlsen.5615LeeOlsen.5615 USUniversity ✭✭

    @nprokopic

    The last solution worked for me except I had to move the logic out of the constructor since View was still null at that point.

    public class TappedViewCell : ViewCell
    {
        public static readonly BindableProperty TappedCommandProperty =
            BindableProperty.Create("TappedCommandProperty", typeof(ICommand), typeof(TappedViewCell), null, propertyChanged: OnTappedCommandChanged);
    
        public ICommand TappedCommand
        {
            get { return (ICommand)GetValue(TappedCommandProperty); }
            set { SetValue(TappedCommandProperty, value); }
        }
    
        protected override void OnAppearing()
        {
            base.OnAppearing();
            OnTappedCommandChanged(this, null, null);
        }
    
        private static void OnTappedCommandChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var viewCell = bindable as TappedViewCell;
    
            if (viewCell == null)
                return;
    
            viewCell.View.GestureRecognizers.Clear();
            viewCell.View.GestureRecognizers.Add(new TapGestureRecognizer() { Command = viewCell.TappedCommand });
        }
    }
    
  • diplopasdiplopas DEMember

    Hi,

    I tried all the different solutions for Android that can be found in this forum. Some of them (e.g. the empty GestureRecognizer) do, in fact, remove the highlighting but also remove other parts of the ListView selection system (like firing the ItemSelected event); or they remove the highlighting color from the cell after it has already been set as its background so that you can briefly see it on slow devices. Both side effects I can't have.

    I tried (amongst other things) things like:

    • Setting a selector for a drawable state (doesn't work; also the selected state of the native ListView is never set);
    • Using the SetItemChecked method of the native ListView (disables highlighting but also the ItemTapped and ItemSelected events of the Forms Element);
    • Replacing/hiding the selection system in a custom ListView (works but is an ugly and laborious workaround that affects all platform implementations);
    • Filtering out the OnPropertyChanged base call for the SelectedItem property in a custom ListView since highlighting only appears when the SelectedItem property has changed (but doesn't work).

    The accepted answer of this thread certainly looks promising if only it would work. Can anyone help me or has at least some ideas?

    Thanks and best regards

  • ThomasBurkhartThomasBurkhart DEMember ✭✭✭✭

    I have done it for Android too you need a custom renderer for the Listview and the ViewCell.

    This is the custom listview Class:

    public class DisplayOnlyListView : Xamarin.Forms.ListView
    {
        public DisplayOnlyListView()
        {
            ItemSelected += DisplayOnlyListView_ItemSelected;
        }
    
        private void DisplayOnlyListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
        {
            SelectedItem = null;
        }
    }
    
    
    
    public class DisplayOnlyViewCell : ViewCell
    {
    }
    

    and the renderers

    [assembly: ExportRenderer(typeof(TBGUI.DisplayOnlyListView), typeof(DisplayOnlyListViewRenderer))]
    namespace TBGUI.Droid
    {
        // DISABLES LISTVIEW ROW HIGHLIGHT
        public class DisplayOnlyListViewRenderer : ListViewRenderer
        {
    
            protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.ListView> e)
            {
                base.OnElementChanged(e);
    
    
                if (Control != null)
                {
                    Control.SetSelector(Android.Resource.Color.Transparent);
                    Control.CacheColorHint = Android.Graphics.Color.Transparent;
                }
            }
    
    
         }
    }
    
    
    using Xamarin.Forms;
    using TBGUI.Droid;
    using Xamarin.Forms.Platform.Android;
    using DroidListView = global::Android.Widget.ListView;
    
    [assembly: ExportRenderer(typeof(TBGUI.DisplayOnlyViewCell), typeof(DisplayOnlyViewCellRenderer))]
    namespace TBGUI.Droid
    {
        // DISABLES LISTVIEW ROW HIGHLIGHT
        public class DisplayOnlyViewCellRenderer : ViewCellRenderer
        {
            protected override Android.Views.View GetCellCore(Cell item, Android.Views.View convertView, Android.Views.ViewGroup parent, Android.Content.Context context)
            {
                var cell = base.GetCellCore(item, convertView, parent, context);
    
                var listView = parent as DroidListView;
    
                if (listView != null)
                {
                    listView.SetSelector(Android.Resource.Color.Transparent);
                    listView.CacheColorHint = Android.Graphics.Color.Transparent;
                }
    
                return cell;
            }
        }
    }
    
  • JohnHardmanJohnHardman GBUniversity mod

    @ThomasBurkhart - By using ItemTapped rather than ItemSelected, it seems to work without any flash of a different background color on Android, without using a custom renderer.

        ItemTapped += OnItemTapped;
    
        private void OnItemTapped(object sender, ItemTappedEventArgs e)
        {
            if ((e != null) && (e.Item != null))
            {
                MyAppNonSelectableListView lv = sender as MyAppNonSelectableListView;
    
                if (lv != null)
                    lv.SelectedItem = null;
            }
        }
    
  • ThomasBurkhartThomasBurkhart DEMember ✭✭✭✭

    @JohnHardman Good to know, I will f´give it a try.

  • diplopasdiplopas DEMember

    @ThomasBurkhart Thanks for your solution. The problem is that it relies on setting the SelectedItem property of the ListView base class to null. Any idea how it can be done without affecting the selection system of the underlying Xamarin ListView?

  • ThomasBurkhartThomasBurkhart DEMember ✭✭✭✭

    @diplopas Did you try the apporach of @JohnHardman ? For my case it was not a problem with the selection system as I did not need selection

  • diplopasdiplopas DEMember

    @ThomasBurkhart Well, the approach of @JohnHardman basically does the same thing by using another event, so, unfortunately, I can't use this either

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    @diplopas for this solution I use (in my viewcell) TapGestureRecognizers, so I don't have to use ItemTapped or ItemSelected and my item in listview is not highlighted..

  • JohnHardmanJohnHardman GBUniversity mod
    edited June 2016

    @diplopas

    Replacing/hiding the selection system in a custom ListView (works but is an ugly and laborious workaround that affects all platform implementations);

    I'm not sure why this affects all platform implementations. Whilst I haven't done it for ListView, I have implemented my own Switch for use on Windows platforms, as the one you get a standard through XF is so limited (actually, I use mine on Android as well now, as it is better than the Android one too IMHO). However, I use the standard XF implementation of Switch on iOS. Whilst I still have Switch wrapped by my class on iOS, there needn't be any overhead other than wrapping the constructor, so I'm not sure why doing the same for ListView would affect all platform implementations other than that tiny overhead.

    I'm also slightly confused by what you are trying to achieve. Am I right in thinking you want selection behavior, but without the background changing to show that a cell is selected? If so, do you want any visual indication at all that a cell is selected? Will the user think of a cell as selected? Would they want some visual indication? Are you supporting users who are using a physical keyboard? Are you supporting users who might be using software tools to assist in accessibility?

  • diplopasdiplopas DEMember

    @JohnHardman The replacing ItemTapped and ItemSelected events of the PCL-ListView have to be triggered by relaying the according events of the native controls in the custom renderers (maybe you know another way?); this is what I meant by affecting all platform implementations.

    I'm building a control library and the usual features of the underlying base controls should stay intact. The visualization of the item selection is done by custom cells.

  • BenPiBenPi USUniversity ✭✭

    I too can't disable this behaviour on listview with the custom renderer or tapped event overwrite (The latter always causes flicker). Very annoying.
    The only solution that does work is the @LeeOlsen.5615 but it makes everything else complicated and screws with internal stuff of the list-elements on plattform-side.

  • AndyMartin.6838AndyMartin.6838 USMember ✭✭

    @JamesMontemagno said:
    You will need a bit of custom rendering:

    On iOS you need to set each cell's
    cell.SelectionStyle = UITableViewCellSelectionStyle.None;

    Kind of like I do here: http://motzcod.es/post/126046400067/adding-a-disclosure-indicator-accessory-to

    On android you will need to get the listview and set:
    listView.SetSelector(Android.Resource.Color.Transparent);
    listView.CacheColorHint = Xamarin.Forms.Color.Transparent.ToAndroid();

    To keep it in CellRenderers you could that stuff like this:
    https://github.com/jamesmontemagno/Hanselman.Forms/blob/master/Hanselman.Android/Renderers/ListImageCellRenderer.cs#L34-L38

    You can instead do this on iOS in your CustomRenderer, and I think it's a little easier.
    Control.AllowsSelection = false;

  • AdrianKnightAdrianKnight USMember ✭✭✭✭
    edited August 2016

    @JamesMontemagno

    listView.SetSelector(Android.Resource.Color.Transparent);
    listView.CacheColorHint = Xamarin.Forms.Color.Transparent.ToAndroid();
    

    does not work for me in material. I tried this in both listview and viewcell renderers.

  • DrEmigiusDrEmigius DEUniversity ✭✭

    If you really want a SelectionMode="None" and disable it completely just set the ListViews InputTransparent="True" so you tap right through it and no selection will ever occur

  • DrEmigiusDrEmigius DEUniversity ✭✭
    edited August 2016

    Btw this will also disable scrolling...
    Putting a scollview around the listview solves this though.

  • JaekovSegoviaJaekovSegovia USMember ✭✭

    This worked for me: Set SelectionStyle property to none, on ios.

    using System;
    using YourSpaceName.iOS;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.iOS;
    [assembly: ExportRenderer(typeof(ViewCell), typeof(ViewCellCustomRenderer))]
    namespace YourSpaceName.iOS
    {
    public class ViewCellCustomRenderer: ViewCellRenderer
    {
    public override UIKit.UITableViewCell GetCell(Cell item, UIKit.UITableViewCell reusableCell, UIKit.UITableView tv)
    {
    var cell = base.GetCell(item, reusableCell, tv);
    Console.WriteLine("Style id: "+ item.StyleId);
    switch (item.StyleId)
    {
    case "none":
    cell.Accessory = UIKit.UITableViewCellAccessory.None;
    cell.SelectionStyle = UIKit.UITableViewCellSelectionStyle.None;
    break;
    default:
    cell.Accessory = UIKit.UITableViewCellAccessory.None;
    break;
    }
    return cell;
    }
    }
    }

  • ISychev93ISychev93 RUMember ✭✭

    Hm hm.. very strange that solution like
    protected override Android.Views.View GetCellCore(Cell item, Android.Views.View convertView, Android.Views.ViewGroup parent, Android.Content.Context context) { var cell = base.GetCellCore(item, convertView, parent, context); var listView = parent as ListView; if (listView != null) { listView.SetSelector(Android.Resource.Color.Transparent); listView.CacheColorHint = Android.Graphics.Color.Transparent; } return cell; }
    work for you, because under hood XF set Background color manually, see CellAdapter.SetSelectedBackground

    protected void SetSelectedBackground(Android.Views.View view, bool isContextTarget = false) { using (TypedValue outValue = new TypedValue()) { if (this._context.Theme.ResolveAttribute(isContextTarget ? 16843662 : 16843664, outValue, true)) view.SetBackgroundResource(outValue.ResourceId); else view.SetBackgroundResource(17170451); } }
    For me work only global change theme, see colorFocusedHighlight, colorPressedHighlight, colorLongPressedHighlight, colorActivatedHighlight, activatedBackgroundIndicator.

  • _dimpy__dimpy_ USMember ✭✭

    @AdrianKnight said:
    @JamesMontemagno

    listView.SetSelector(Android.Resource.Color.Transparent);
    listView.CacheColorHint = Xamarin.Forms.Color.Transparent.ToAndroid();
    

    does not work for me in material. I tried this in both listview and viewcell renderers.

    @AdrianKnight Did you find a solution to getting it working with material?

  • AdrianKnightAdrianKnight USMember ✭✭✭✭
    edited October 2016

    I went with the sample in the OP's question.

  • AlanSpiresAlanSpires USBeta ✭✭

    public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv) { var cell = base.GetCell(item, reusableCell, tv); if (cell != null) { cell.SelectionStyle = UITableViewCellSelectionStyle.None; item.Tapped += (a, b) => { UpdateBackground(cell, item); }; } return cell; }

    Is the only solution that seems to work on iOS when using ListView.IsGroupingEnabled = true;

  • I found creating a custom iOS ViewCellRenderer and setting cell.SelectionStyle = UITableViewCellSelectionStyle.None did not work. I have found that setting tv.AllowsSelection = false does work. However, if I set tv.AllowsElection to false, and CacheStrategy is not RecycleElement, then bindings to SelectedItem do not work (the setter for the property bound to ListViewSelectedItem does not fire). Anyone run into this? I can just always set CachingStrategy to RecycleElement, I just feel bad for the next guy who will run into this.

    I'd like to creating a custom ListViewRenderer that throws an assertion if the caching strategy is not RecycleElements but SelectedItem is bound. I haven't found a way to check if SelectedItem is bound though.

  • ShimmyWeitzhandlerShimmyWeitzhandler USMember ✭✭✭
    edited June 2017

    Isn't it about time to enhance the ListView control?

    Horizontal rendering, repeater functionality (ItemsControl), better sizing options (size to content), control over scrollbars, these silly features require custom renderers x3-4. And besides why Cells? Why not a ContentView like WPF's ContentControl to enable templating of a single item.
    Also Grid.IsSharedSizeGroup is missing!

  • These solutions, consolidated from above comments and tested, will allow items to be selected so you can handle the event if you want but will suppress highlighting/flickering.

    iOS custom ViewCellRenderer:

    using Xamarin.Forms;
    using Xamarin.Forms.Platform.iOS;

    [assembly: ExportRenderer(typeof(ViewCell), typeof(MobileAgent.iOS.CustomViewCellRenderer))]
    namespace MobileAgent.iOS
    {
    public class CustomViewCellRenderer : ViewCellRenderer
    {
    public override UIKit.UITableViewCell GetCell(Cell item, UIKit.UITableViewCell reusableCell, UIKit.UITableView tv)
    {
    var cell = base.GetCell(item, reusableCell, tv);

            cell.SelectionStyle = UIKit.UITableViewCellSelectionStyle.None;
            item.Tapped += (sender, e) =>
            {
                UpdateBackground(cell, item);
            };
    
            return cell;
        }
    }
    

    }

    Android custom ViewCellRenderer:

    using Xamarin.Forms;
    using Xamarin.Forms.Platform.Android;

    using View = Android.Views.View;
    using ViewGroup = Android.Views.ViewGroup;
    using Context = Android.Content.Context;
    using ListView = Android.Widget.ListView;

    [assembly: ExportRenderer(typeof(ViewCell), typeof(MobileAgent.Android.CustomViewCellRenderer))]
    namespace MobileAgent.Android
    {
    public class CustomViewCellRenderer : ViewCellRenderer
    {
    protected override View GetCellCore(Cell item, View convertView, ViewGroup parent, Context context)
    {
    if (parent is ListView)
    {
    ((ListView)parent).SetSelector(Resource.Color.Transparent);
    ((ListView)parent).CacheColorHint = Color.Transparent.ToAndroid();
    }

            return base.GetCellCore(item, convertView, parent, context);
        }
    }
    

    }

    Add this color resource:

    <?xml version="1.0" encoding="UTF-8" ?>

    #00000000

    Put this in page xaml:

            <ListView ... ItemSelected="OnItemSelected" ...>
    

    Put this in page class:

        public void OnItemSelected (object sender, SelectedItemChangedEventArgs args)
        {
            ((ListView)sender).SelectedItem = null;
        }
    
  • Trying color resource code again:

        <?xml version="1.0" encoding="UTF-8" ?>
        <resources>
            <color name="Transparent">#00000000</color>
        </resources>
    
  • pdanielpdaniel ROMember ✭✭

    Hello,

    @Don Coulombe - the solution is not working if you have on the list : CachingStrategy="RecycleElement"

    Any suggestions?

    Regards

  • pdanielpdaniel ROMember ✭✭

    I tested the solution on IOS

  • saadhaffar025saadhaffar025 MAMember
    edited September 2017

    Hi,
    I've been testing for 2 hours a lot of solutions. I found 2 solutions working, both solutions are keeping the event ItemSelected working and both of them are using only a custom renderer. I share with the two working ones for iOS:

    using System;
    using Project.iOS.Renderers;
    using UIKit;
    using Xamarin.Forms;
    
    [assembly: ExportRenderer(typeof(ViewCell), typeof(ViewCellRenderer))]
    
    namespace Project.iOS.Renderers
    {
        public class ViewCellRenderer : Xamarin.Forms.Platform.iOS.ViewCellRenderer
        {
            public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
            {
                reusableCell = base.GetCell(item, reusableCell, tv);
    
                //First working solution (Works alone without second one).
                reusableCell.SelectionStyle = UITableViewCellSelectionStyle.None;
    
                //Second working solution (Works alone without first one). May be used to customize the selection color as you like. You may pass it over custom ViewCell from your PCL.
                //reusableCell.SelectedBackgroundView = new UIView
                //{
                //  BackgroundColor = UIColor.Clear,
                //};
    
                return reusableCell;
            }
        }
    }
    
  • AdrianGhiAdrianGhi USMember ✭✭

    @JaekovSegovia

    Your solution worked for me. Thank you a lot!

  • sinegolesinegole Member
    edited May 2018

    One very simple solution from XAML

    Set <ViewCell.View>Grid BackgroundColor="Red">

Sign In or Register to comment.