fabulous-dev / Fabulous.XamarinForms

Declarative UIs for Xamarin.Forms with F# and MVU, using Fabulous
https://docs.fabulous.dev/xamarinforms
Apache License 2.0
13 stars 1 forks source link

ListView: disable animation when selectedItem changes #9

Open nghia-bui opened 4 years ago

nghia-bui commented 4 years ago

I have a ListView like this:

View.ListView (
  selectionMode = ListViewSelectionMode.Single,
  selectedItem = model.SelectedIndex,
  itemSelected = Option.iter (UpdateSelectedIndex >> dispatch),
  items = [ for name in model.Names do yield itemView name ]
)

Problem is that the items (with new content) are shown immediately in the UI, but the selected item is highlighted a little bit late due to the animation.

How to disable this animation?

SergejDK commented 3 years ago

@nghia-bui just to be clear - you don't want to be able to highlight any row in the list? Or better would be if you have a example app where I can check this directly.

If it is the case you can do the following:

  1. Create a customrenderer in this example I did it with iOS.

    type MyListViewRenderer() =
    inherit ListViewRenderer()
    
    override this.OnElementPropertyChanged(sender: obj, e: PropertyChangedEventArgs) =
        base.OnElementPropertyChanged(sender, e)
    
        match e.PropertyName with
        | "SelectedItem" ->
            match this.Element, this.Control with
            | null, null -> ()
            | _ ->
                this.Control.VisibleCells
                |> Array.iter (fun v -> v.SelectionStyle <- UITableViewCellSelectionStyle.None )
        | _ -> ()
  2. Export this Renderer

    [<assembly: ExportRenderer(typeof<Fabulous.XamarinForms.CustomListView>, typeof<MyListViewRenderer>)>]

This way the renderer is going to work for every View.ListView.

If you only want to modify one specific ListView then you need to create your own type as follows:

module TestListViewModule =
    type TLV() = inherit CustomListView()

    type Fabulous.XamarinForms.View with 

            static member inline TestListView(?items: ViewElement list, ?itemAppearing: int -> unit, ?itemSelected: int option -> unit) = 

                let attribCount = 0
                let attribs = ViewBuilders.BuildListView(attribCount, ?items=items, ?itemAppearing=itemAppearing, ?itemSelected=itemSelected)

                let update (prevOpt: ViewElement voption) (source: ViewElement) (target: TLV) =
                    ViewBuilders.UpdateListView(prevOpt, source, target)

                let updateAttachedProperties propertyKey prevOpt source targetChild =
                    ViewBuilders.UpdateListViewAttachedProperties(propertyKey, prevOpt, source, targetChild)

                ViewElement.Create<TLV>(TLV, update, updateAttachedProperties, attribs)

And to make it work for this specific type you have to change the export part. In the following example just use the path to your type.

[<assembly: ExportRenderer(typeof<AllControls.Samples.TestListViewModule.TLV>, typeof<MyListViewRenderer>)>]