firemonkeyfiremonkey-style

ListBox selected item always have a default background opacity of 0.7


The problem as it is. No matter what color you use in your style as the selection color for the ListBox item, it is always displayed with opacity set to 0.7.

Suppose I want to set the selection color to black. I get the following style:

object TRectangle
  StyleName = 'ListBoxstyle'
  Align = Center
  Fill.Color = claWhite
  HitTest = False
  Margins.Bottom = 2.000000000000000000
  Size.Width = 200.000000000000000000
  Size.Height = 200.000000000000000000
  Size.PlatformDefault = False
  Stroke.Kind = None
  XRadius = 12.500000000000000000
  YRadius = 12.500000000000000000
  object TLayout
    StyleName = 'content'
    Align = Client
    ClipChildren = True
    Margins.Left = 3.000000000000000000
    Margins.Top = 3.000000000000000000
    Margins.Right = 4.000000000000000000
    Margins.Bottom = 3.000000000000000000
    Size.Width = 185.000000000000000000
    Size.Height = 194.000000000000000000
    Size.PlatformDefault = False
    object TRoundRect
      StyleName = 'selection'
      Fill.Color = claBlack
      HitTest = False
      Size.Width = 50.000000000000000000
      Size.Height = 50.000000000000000000
      Size.PlatformDefault = False
      Stroke.Kind = None
    end
  end
end

Below is a picture of the expected and actual result of displaying a ListBox for a ComboBox:

After some effort and research, I found the following section in the FMX.ListBox.hpp file:

private:
    #define TCustomListBox_UnfocusedSelectionOpacity  (7.000000E-01)
    
    #define TCustomListBox_ExtendedSelectionOpacity  (7.000000E-01)

After manually deselecting each item in a loop before a ComboBox drops its ListBox down (OnEnter event), the selection color is displayed as plain black, as expected:

for (int i = 0; i < combo_box->ListBox->Items->Count; i++)
    combo_box->ListBox->ListItems[i]->IsSelected = false;

But I can't use this workaround because I need to use the Selected property. Is there a way to override the default opacity or turn it off completely?


Solution

  • Hmm… After looking at those strings in the FMX.ListBox.pas file:

    // ...
        if FindStyleResource<TControl>('selection', FSelection) then
          FSelection.Visible := False;
        if FindStyleResource<TControl>('focusedselection', FFocusedSelection) then
          FFocusedSelection.Visible := False;
        if (FFocusedSelection = nil) and FindAndCloneStyleResource<TControl>('selection', SelectionControl) then
        begin
          FFocusedSelection := SelectionControl;
          FFocusedSelection.Parent := FSelection.Parent;
          FFocusedSelection.Visible := False;
          FSelection.Opacity := UnfocusedSelectionOpacity;
        end;
        if FindStyleResource<TControl>('extendedselection', FExtendedSelection) then
          FExtendedSelection.Visible := False;
        if (FExtendedSelection = nil) and FindAndCloneStyleResource<TControl>('selection', SelectionControl) then
        begin
          FExtendedSelection := SelectionControl;
          FExtendedSelection.Parent := FSelection.Parent;
          FExtendedSelection.Opacity := ExtendedSelectionOpacity;
          FExtendedSelection.Visible := False;
        end;
    // ...
    

    And understanding them (or not), adding empty focusedselection and extendedselection Layouts to the style:

    object TLayout
      StyleName = 'focusedselection'
    end
    object TLayout
      StyleName = 'extendedselection'
    end
    

    Seems to have solved the problem. Perhaps this is one of those cases where you need a chamber of understanding to make sense of it all.