Skip to content

FMX: botones con imágenes

A diferencia de su equivalente VCL, el TSpeedButton de FireMonkey no posee la propiedad Glyph de la misma manera, y el TButton no posee la propiedad de agregar imágenes en la versión VCL, y en FMX, no existe la clase TBitBtn para hacer algo similar.

La razón de esto es que, en principio, no hay necesidad de poseer un componente con estas propiedades de imágenes, porque lo podemos realizar de forma muy sencilla siguiendo estos pasos.

FMX: Crear TButton con imágenes

Creamos un nuevo proyecto en FMX (Multi-device en las ultimas versiones de Delphi).

A continuación, arrastramos al formulario un TButton y un TImage.

Tengamos en cuenta que en el desarrollo bajo FMX, todo componente es un contenedor. Así que desde la vista de estructura del IDE, arrastramos el TImage dentro del TButton, quedando de la siguiente manera:

Ahora seleccione el TImage y establezca la propiedad HitTest en False y un Align igual a Left. Este indicará que no posea eventos del mouse en la imagen, si no que se comporte como el contenedor, en este caso el TButton.

Luego de probar, me he dado con un grave problema. Sabemos que el TButon como todo otro componente se componen de controles FMX más primitivos, en este caso, esta compuesto por un TShape y un TText, el TText posee un align al TShape que no se modifica en absoluto al contener el TImage. Quedando un TLabel totalmente desalineado con respecto al TImage.

Inclusive, si ven la imagen anterior, he probado alinear el texto en Center y Rigth y queda verdaderamente horrible de ambas maneras. La solución en primera instancia es no ponerle el texto al TButton, pero no la verdadera solución. Pero a no desesperarse, FMX nos brinda solución a todo este rollo.

Evento OnApplyStyleLookup, solución a botones con imágenes

FMX nos brinda un evento llamado OnApplyStyleLookup, dicho evento se dispara al cargarse o recargarse el estilo del componente, y en él podremos modificar las propiedades del TText para que se acomode de acuerdo al TImage.

Después de programar un tiempo largo, he construido este procedimiento que asigna un margen al TText del TButtom igual al tamaño del TImage. Solo debe asignar este procedimiento del evento OnApplyStyleLookup y quedará solucionado el problema de la alineación.

procedure TForm1.ApplyStyleLookup(Sender: TObject);
var
  Button: TCustomButton;
  Control: TControl;
  TextObj: TFmxObject;
begin
  Button := (Sender as TCustomButton);
  for Control in Button.Controls do
  begin
    if Control is TImage then
    begin
      TextObj := Button.FindStyleResource('text');

      if TextObj is TText then
        case Control.Align of
          TAlignLayout.alLeft:
            (TextObj as TText).Margins.Left := Control.Width;
          TAlignLayout.alTop:
            (TextObj as TText).Margins.Top := Control.Height;
          TAlignLayout.alRight:
            (TextObj as TText).Margins.Right := Control.Width;
          TAlignLayout.alBottom:
            (TextObj as TText).Margins.Bottom := Control.Height;
        end;
      Break;
    end;
  end;
end;

Lo que realiza básicamente este procedimiento es verificar la alineación del TImage y asignarle un margen de la misma alineación al TText. (Si el TImege posee un Align = Left, asignamos un Margins.Left al TText. Y el resultado final es el siguiente: