Páginas

terça-feira, 29 de setembro de 2020

Toast Notification Android no Delphi


Olá novamente, recruta!

Hoje vamos falar sobre notificações Toast no Android utilizando Delphi FireMonkey .

Rapidamente para quem não está familiarizado com o assunto, Toast Notidication se refere a pequenas mensagens pop-up que aparecem na tela do mobile quando efetuamos algumas operações em certos Apps, como enviar um e-mail ou o concluir um download.

Essas notificações permanecem por um tempo na tela e depois somem, elas não impedem ou bloqueiam a execução da tela atual, ou seja, não são janelas modais, inclusive, mesmo que nossa aplicação seja finalizada elas permanecerão na tela pelo tempo que foi configurado.

Existem algumas formas de emular um Toast Notification, algumas bem difundidas na internet, o que de certa forma é bem interessante, ao ponto que não ficamos preso a uma plataforma específica, mas não é tão eficiente quanto usar o Toast nativo da plataforma. A forma  que nós iremos utilizar será com a própria API do Toast Notification do Android, consequentemente você não poderá utilizar no Windows nem no IOS.

Antes de tudo um pouquinho de história.

O primeiro a disponibilizar uma API para usar Toast no Delphi foi o MVP Embarcadero Brian Long (http://blong.com), que criou uma Unit com esta implementação, a Android.JNI.Toast.pas. 
Essa Unit já é bastante utilizada no mundo todo. 
Nas ultimas versões do Delphi essa API foi incorporada e está presente na Unit Androidapi.JNI.Widget.pas.


No Delphi, ao contrário da Unit criada por Brian, não temos um método pronto para invocarmos o Toast, então para nossa primeira implementação e teste vamos utilizar o método criado por Brian como referência:

 
interface
type
  TToastLength = (LongToast, ShortToast);

procedure Toast(const Msg: string; Duration: TToastLength = ShortToast);

Implementation

procedure Toast(const Msg: string; Duration: TToastLength);
var
  ToastLength: Integer;
begin
  if Duration = ShortToast then
    ToastLength := TJToast.JavaClass.LENGTH_SHORT
  else
    ToastLength := TJToast.JavaClass.LENGTH_LONG;

  CallInUiThread(procedure
  begin
    TJToast.JavaClass.makeText(SharedActivityContext, StrToJCharSequence(msg),
      ToastLength).show;
  end);
end;


Como podemos observar, para chamar um Toast Notification é bastante simples, basta instanciarmos um JToast utilizando o método makeText passando os devidos parâmetros e depois executar o método show para que a mensagem seja exibida na tela.

O Método MakeText exige 3 parâmetros:

- Context : A grosso modo seria algo como o handle da sua aplicação ou do formulário principal no Windows, o Self.Handle, no firemonkey, para o Android, podemos usar o TAndroidHelper.Context disponível na Unit Androidapi.Helpers;

- Text: O texto que será exibido no Toast em formato JCharSequence. Para converter sua String utilize o método StrToJCharSequence também na Unit Androidapi.Helpers;

- Duration: O tempo de exibição do Toast. Esse parâmetro mesmo sendo um inteiro só aceita dois valores, 0 para período curto ou 1 para período longo. Para não haver surpresas futuras, principalmente devido as milhares de customizações de Androids por aí,  recomenda-se usar a  propriedade  TJToast.JavaClass.LENGTH_SHORT para períodos curtos e TJToast.JavaClass.LENGTH_LONG para períodos longos.

O MakeText deve ser executado sempre na thread principal, então para garantir isso efetuamos a chamada através de um método anônimo utilizando o método CallInUiThread;

De uma forma bastante simples, bastaríamos fazer algo como:


 
CallInUiThread(
procedure
begin
  TJToast.JavaClass.makeText(
    TAndroidHelper.Context,
          StrToJCharSequence('Teste de Toast Notification'),
          TJToast.JavaClass.LENGTH_SHORT).show
  	end);


Exemplo de chamada de Toast Notification


Agora que sabemos como chamar um Toast Notification vamos construir uma classe para tornar nosso processo mais reutilizável.

Vamos criar uma nova unit uToastNotification, e a nossa classe será a TToastNotification. 

Também iremos criar um tipo enumerado para facilitar a definição da Duração da notificação.

Em nossa classe iremos declarar um método de classe chamado Show, apenas com dois parâmetros, a mensagem a ser exibida como string e a duração usando nosso tipo enumerado.  Esse método será usado para invocar nosso Toast Notification. Optamos por utilizar um método de classe, assim não precisaremos instanciar um objeto para efetuar a chamada do método.


unit uToastNotification;

interface
uses
  Androidapi.JNI.Widget;

type
  TToastLength = (ShortToast, LongToast);

  TToastNotification = class
  public
    class procedure Show(pMsg: string; pDuration: TToastLength = ShortToast);
  end;

implementation
uses
  FMX.Helpers.Android, Androidapi.Helpers, Androidapi.JNI.JavaTypes;

{ TToastNotification }

class procedure TToastNotification.Show(pMsg: string; pDuration: TToastLength);
var
  lToastLength: Integer;
begin
  if pDuration = ShortToast then
    lToastLength := TJToast.JavaClass.LENGTH_SHORT
  else
    lToastLength := TJToast.JavaClass.LENGTH_LONG;

  CallInUiThread(procedure
  begin
    TJToast.JavaClass.makeText(TAndroidHelper.Context,
                               StrToJCharSequence(pMsg),
                               lToastLength).show;
  end);
end;


Para usar nosso código basta fazer a seguinte chamada:

TToastNotification.Show('Teste de Toast Notification');

Isso já irá exibir nossa janela com um período curto, para um período logo basta adicionar o parâmetro LongToast

TToastNotification.Show('Teste de Toast Notification', LongToast);

 

Pausa para uma refatoração!

Antes de adicionarmos mais funcionalidades ao nosso Toast, como a seleção de cores por exemplo, vamos fazer uma pequena refatoração.

Vou adicionar um Record Helper ao nosso tipo enumerado TToastLength para facilitar a conversão para o inteiro utilizado no método TJToast.JavaClass.makeText.


TToastLengthHelper = record helper for TToastLength
  function ToAndroidLength: integer;
end;

{ TToastLengthHelper }

function TToastLengthHelper.ToAndroidLength: integer;
begin
  case self of
    ShortToast: result := TJToast.JavaClass.LENGTH_SHORT;
    LongToast: result := TJToast.JavaClass.LENGTH_LONG;
  end;
end;


Agora podemos remover aquele "if" inicial do nosso método show


 
class procedure TToastNotification.Show(pMsg: string; pDuration: TToastLength);
begin
  CallInUiThread(procedure
  begin
    TJToast.JavaClass.makeText(TAndroidHelper.Context,
                               StrToJCharSequence(pMsg),
                               pDuration.ToAndroidLength).show;
  end);
end;


Muito melhor de bom, não acham?!


Além de apenas exibir um texto dentro do Toast padrão do android, podemos fazer uma série de outras alterações, como a cor do Toast, fonte, tamanho, posicionamento, inclusive substituir o Toast por outro objeto.


JToast  

Se olharmos a Interface JToast que está na unit Androidapi.JNI.Widget.pas, podemos observar alguns métodos, uns bem óbvios como SetText, e SetDuration que passamos diretamente pelos parâmetros do método makeText, mas que podem ser modificados através do acesso de uma variável do tipo JToast.


 
  [JavaSignature('android/widget/Toast')]
  JToast = interface(JObject)
    ['{410DDA5F-7D4B-415E-8BE4-F545D331176C}']
    procedure cancel; cdecl;
    function getDuration: Integer; cdecl;
    function getGravity: Integer; cdecl;
    function getHorizontalMargin: Single; cdecl;
    function getVerticalMargin: Single; cdecl;
    function getView: JView; cdecl;
    function getXOffset: Integer; cdecl;
    function getYOffset: Integer; cdecl;
    procedure setDuration(duration: Integer); cdecl;
    procedure setGravity(gravity: Integer; xOffset: Integer; yOffset: Integer); cdecl;
    procedure setMargin(horizontalMargin: Single; verticalMargin: Single); cdecl;
    procedure setText(resId: Integer); cdecl; overload;
    procedure setText(s: JCharSequence); cdecl; overload;
    procedure setView(view: JView); cdecl;
    procedure show; cdecl;
  end;
  
  TJToast = class(TJavaGenericImport<JToastClass, JToast>) 
  end;


GetView

O método GetView retorna a Interface para acessarmos o Objeto que é exibido pelo Toast.

Através do GetView podemos alterar diversas características do Toast, como cor, tamanho e posicionamento.

Continuando a implementação da nossa classe para manipulação do Toast vamos declarar as suas propriedades  conforme formos aprendendo a manipular mais recursos.


   
  TToastNotification = class
  private
    FText: string;
    FDuration: TToastLength;
    FColor: TAlphaColor;
  public
    class procedure Show(pMsg: string; pDuration: TToastLength = ShortToast); overload;
    procedure Show; overload;
    property Text: string read FText write FText;
    property Duration: TToastLength read FDuration write FDuration;
    property Color: TAlphaColor read FColor write FColor;
  end;


Conforme visto no código em acima, adicionei as propriedades que já conhecemos e inclui a propriedade Color. Também declarei um overload do Método Show. Diferente do anterior esse é um método do objeto e não da classe, será chamado a partir de uma instância do TToastNotification.

 

Alterando Cor 

Nosso método Show irá retornar a interface JToast para nossa variável, assim podemos acessar a View do Toast e através do método setBackgroundColor poderemos alterar a cor de fundo do Toast.


 
procedure TToastNotification.Show;
begin
  CallInUiThread(procedure
  var
    lToast: JToast;
  begin
    lToast := TJToast.JavaClass.makeText(TAndroidHelper.Context,
                               StrToJCharSequence(FText),
                               FDuration.ToAndroidLength);

    lToast.getView.setBackgroundColor(FColor);
    lToast.show;
  end);
end;


Testando nossa classe

 

Criei um App para testarmos nossa classe, nele eu adicionei um TEdit o qual chamei de edtText e um TColorComboBox como nome de ColorComboBox. 

Coloquei dois botões, o primeiro o nomeei para btnShowToast e chamei o método da classe Show;


 
procedure TfrmToastNotification.btnShowToastClick(Sender: TObject);
begin
  TToastNotification.Show(edtText.Text);
end;


O segundo botão chamei de btnShowToastColor e utilizei o método show do Objeto.


 
procedure TfrmToastNotification.btnShowToastColorClick(Sender: TObject);
var
  lToastNotification : TToastNotification;
begin
  lToastNotification := TToastNotification.Create;
  try
    lToastNotification.Text := edtText.Text;
    lToastNotification.Duration := TToastLength.LongToast;
    lToastNotification.Color := ColorComboBox.Color;
    lToastNotification.Show;
  finally
    lToastNotification.Free;
  end;
end;

 

App para teste de Toast Notification


O primeiro método gerou o Toast padrão do Android (o formato pode variar conforme a versão do Android e fabricante do seu mobile), no meu caso ele retornou com um layout Cinza de bordas arredondadas com a mensagem que passamos por parâmetro.

 

Toast retornado pelo método btnShowToastClick


Já o segundo botão, gerou um Toast na cor que atribuímos para a propriedade Color de nosso objeto. Mas desta vez ele perdeu as bordas arredondadas. Isso ocorreu porque alteramos a cor do background da View, substituindo o desenho original.

  

Toast retornado pelo método btnShowToastColorClick

 

Uma maneira de manter o formato original é entrar um pouco mais a fundo na JView e aplicar um filtro de cor diretamente na propriedade Background da View. 

O Background da View possui um método chamado setColorFilter com dois parâmetros, a cor que iremos aplicar e o modo como ela será aplicada (PorterDuff.Mode). 

O filtro que iremos aplicar é o SRC_IN, que irá cobrir todos os pixels visíveis com a cor selecionada. Para mais informações sobre os filtros disponíveis veja a documentação do Android em https://developer.android.com/reference/android/graphics/PorterDuff.Mode 

No Delphi a constante PorterDuff.Mode.SRC_IN fica TJPorterDuff_Mode.JavaClass.SRC_IN

Então substituímos nossa chamada de:

   lToast.getView.setBackgroundColor(FColor);

para

   lToast.getView.getBackground.setColorFilter(FColor, TJPorterDuff_Mode.JavaClass.SRC_IN);


 
procedure TToastNotification.Show;
begin
  CallInUiThread(procedure
  var
    lToast: JToast;
  begin
    lToast := TJToast.JavaClass.makeText(TAndroidHelper.Context,
                               StrToJCharSequence(FText),
                               FDuration.ToAndroidLength);

    lToast.getView.getBackground.setColorFilter(FColor, TJPorterDuff_Mode.JavaClass.SRC_IN)
    lToast.show;
  end);
end;

 

Toast retornado pelo método btnShowToastColorClick após o ajuste

 

 

Alinhamento

Também podemos trabalhar o alinhamento e tamanho do Toast através do método SetGravity. 

Neste método passamos o Gravity, que é o posicionamento que queremos utilizar, como Top, Bottom, e mais uma série de opções (A lista completa de opções pode ser verificada em https://developer.android.com/reference/android/view/Gravity), 

O Delphi fornece as opções através do TJGravity na Unit Androidapi.JNI.GraphicsContentViewText, onde podemos concatena-las utilizando o operador “OR” por exemplo:

TJGravity.JavaClass.AXIS_CLIP or TJGravity.JavaClass.BOTTOM

Os outros dois parâmetros do método SetGravity é relacionado a posição em pixels onde o Toast irá ser mostrado, XOffset e YOffset. Por exemplo, se alinhado em Top ou Bottom o YOffset funcionará como uma margem.

Mas tem um segredinho, o valor usado para X e Y não é o mesmo valor que estamos acostumados a usar nas posições e tamanhos no Delphi então precisamos fazer a conversão usando o método ConvertPointToPixel.

Digamos que você queira fazer um alinhamento superior com um espaço de 200 do Top da aplicação.


 
var lPointF := ConvertPointToPixel(TPointF.Create(0,200));
    lToast.setGravity((TJGravity.JavaClass.AXIS_CLIP or TJGravity.JavaClass.TOP),
                      Trunc(lPointF.X),Trunc(lPointF.Y));
                      


Vamos adicionar estes novos recursos a nossa classe, criando mais 3 propriedades. Gravity, XOffset e YOffset, todos do tipo Integer.

Também declarei um construtor para iniciar o Gravity com -1, indicando que ele não será modificado.


 
  TToastNotification = class
  private
    FText: string;
    FDuration: TToastLength;
    FColor: TAlphaColor;
    FXOffset: Integer;
    FYOffset: Integer;
    FGravity: integer;
  public
    constructor Create;
    class procedure Show(pMsg: string; pDuration: TToastLength = ShortToast); overload;
    procedure Show; overload;
    property Text: string read FText write FText;
    property Duration: TToastLength read FDuration write FDuration;
    property Color: TAlphaColor read FColor write FColor;
    property Gravity: integer read FGravity write FGravity;
    property XOffset: Integer read FXOffset write FXOffset;
    property YOffset: Integer read FYOffset write FYOffset;
  end;

constructor TToastNotification.Create;
begin
  FGravity := -1;
end;


No nosso método Show adicionamos o teste para a implementação do Gravity.


 
procedure TToastNotification.Show;
begin
  CallInUiThread(procedure
  var
    lToast: JToast;
  begin
    lToast := TJToast.JavaClass.makeText(TAndroidHelper.Context,
                               StrToJCharSequence(FText),
                               FDuration.ToAndroidLength);
    
    lToast.getView.getBackground.setColorFilter(FColor,    TJPorterDuff_Mode.JavaClass.SRC_IN);
    
    if FGravity <> -1 then
    begin
      var lPointFGravity:= ConvertPointToPixel(TPointF.Create(FXOffset,FYOffset));
      lToast.setGravity(FGravity,Trunc(lPointFGravity.X),Trunc(lPointFGravity.Y));
    end;

    lToast.show;
  end);
end;


A alteração do Gravity fica bastante simples. Vou deixar fixo no nosso btnShowToastColorClick para fazer um alinhamento Top com espaço de 200 do topo da aplicação, mas você já entendeu como funciona!


 
lToastNotification.Gravity := TJGravity.JavaClass.AXIS_CLIP or TJGravity.JavaClass.TOP;
lToastNotification.XOffset := 0;
lToastNotification.YOffset := 200;

 

Tamanho

A alteração do tamanho do Toast podemos utilizar os métodos setMinimumWidth e setMinimumHeight da View. Como o próprio nome já diz, ele irá definir o tamanho mínimo da View.

Lembrando que sempre que nos referirmos a dimensões temos que utilizar o método ConvertPointToPixel para termos as dimensões corretas em relação ao que utilizamos no design do Delphi.

A View possui ainda uma série de outros método que podem ser utilizados para customizar seu Toast, como rotação, escalas entre outros.

A interface JToast ainda possui configurações de margem horizontal e vertical.

 

Texto

Nosso último tópico vamos falar sobre a customização de cor e tamanho do texto do Toast.

Essa parte é um pouco mais complicada, porque não existe dentro do View do Toast um método que nos retorne o texto para que possamos customiza-lo. 

Então como podemos fazer isso?

Procurando um pouco na internet, é fácil achar a seguinte técnica para alterar a cor do texto de um Toast:


 
Toast toast = Toast.makeText(context, TEXT, duration);
View view = toast.getView();
TextView text = view.findViewById(android.R.id.message);
text.setTextColor(YOUR_TEXT_COLOUR);
toast.show();


Se verificarmos esse código Java, veremos que já fazemos o MakeText e temos o getView retornando a View do Toast. O que precisamos fazer agora é buscar a TextView que está dentro da View do Toast, e é justamente essa parte que ninguém conta como se faz em Delphi. 

Não contavam até agora!

O método FindViewById precisa do ID do item que queremos buscar. Se olharmos a documentação do Android expecificamente para o Objeto android.R.ID descobriremos que Message é uma constante de valor 16908299. (https://developer.android.com/reference/android/R.id.html#message) .

Mas como meu velho pai costumava dizer:
- Filho, nunca confie em números mágicos!

No Android os componentes do tipo Views geralmente possuem um ID, e a TextView do Toast, assim como um AlertDialog (outro tipo de janelinha de mensagem do Android) utilizam essa mesma constante para identificar sua View de Texto. Dessa forma eu posso usar essa constante e ser feliz. Pelo menos até o Android decidir em alguma nova versão que esse número não é tão mágico assim.

Obedecendo os conselhos do meu velho pai vamos usar um método para retornar esse ID, assim como é feito no Java.

Então android.R.id.message vira:


 
TAndroidHelper.Activity.getResources.getIdentifier(
                                   StringToJString('message'),
                                   StringToJString('id'),
                                   StringToJString('android'));


Agora que temos nosso ID basta passá-lo para o método FindViewById e retornar a nossa View.


 
var lResourceID := TAndroidHelper.Activity.getResources.getIdentifier(
                                   StringToJString('message1'),
                                   StringToJString('id'),
                                   StringToJString('android'));

if lResourceID <> 0 then
begin
  var lView := lToast.getView.findViewById(lResourceID);

end;


Em teoria como a interface JViewText é uma implementação da interface JView e sabemos que o retorno desejado é um JViewText bastaria fazermos um Type Cast para o tipo desejado e tudo funcionaria como esperado, algo como:

 
    var lText: JTextView;
    lText := (lView as JTextView);

 

Certo? Errado!

Acontece que quando trabalhamos com os objetos Java do android, estamos acessando apenas interfaces e elas não tem o mesmo dinamismo de classes e objetos que estamos acostumados. Quando chamamos o FindViewById, ele retornou uma série de ponteiros de memória para acessarmos um JView e todo o restante passa a ser ignorado. Mesmo que você teste o método Suports para verificar se o JView retornado tem suporte ao JTextView, verá que não. Tudo irá indicar que ele não é um JTextView.

E como resolvemos isso, já que temos certeza absoluta de que essa JView é um JTextView?

Toda interface Java no Delphi possui uma classe herdada de TJavaGenericImport que sem nos estendermos muito nos detalhes, ela funciona como uma classe de apoio para toda essa comunicação entre as classes Java do Android e o Delphi. E um destes métodos é o Wrap. Com ele podemos fazer a carga correta da interface esperada a partir de uma interface mais abstrata.

Assim utilizamos o objeto TJTextView para carregar nosso JTextView corretamente. 

Nossa implementação fica desta forma:

 
    var lText: JTextView;
lText:= TJTextView. Wrap(lView);


E agora que temos o JTextView referente ao texto do Toast basta chamar os métodos setTextColor e setTextSize para alterar a cor e tamanho do texto. 

Para a implementação da nossa classe eu adicionei 3 propriedades. CustomText (Boolean), para indicar que iremos customizar o texto, TextColor (TAlphaColor) e TextSize (Single), respectivamente a cor e tamanho da fonte. 


    property CustomText: Boolean read FCustomText write FCustomText;
    property TextColor: TAlphaColor read FTextColor write FTextColor;
    property TextSize: Single read FTextSize write FTextSize;


Nosso método Show finalizado fica com a seguinte implementação


constructor TToastNotification.Create;
begin
  FGravity := -1;
end;

procedure TToastNotification.Show;
begin
  CallInUiThread(procedure
  var
    lToast: JToast;
  begin
    lToast := TJToast.JavaClass.makeText(TAndroidHelper.Context,
                               StrToJCharSequence(FText),
                               FDuration.ToAndroidLength);

    lToast.getView.getBackground.setColorFilter(FColor, TJPorterDuff_Mode.JavaClass.SRC_IN);
    if FGravity <> -1 then
    begin
      var lPointFGravity := ConvertPointToPixel(TPointF.Create(FXOffset,FYOffset));
      lToast.setGravity(FGravity,Trunc(lPointFGravity.X),Trunc(lPointFGravity.Y));
    end;

    var lPointFTamanho := ConvertPointToPixel(TPointF.Create(FMinimumWidth,FMinimumHeight));
    lToast.getView.setMinimumWidth(Trunc(lPointFTamanho.X));
    lToast.getView.setMinimumHeight(Trunc(lPointFTamanho.Y));


    if FCustomText then
    begin
      var lResourceID := TAndroidHelper.Activity.getResources.getIdentifier(
                                   StringToJString('message'),
                                   StringToJString('id'),
                                   StringToJString('android'));

      if lResourceID <> 0 then
      begin
        var lText := TJTextView.wrap(lToast.getView.findViewById(lResourceID));
        lText.setTextColor(FTextColor);
        lText.setTextSize(FTextSize);
      end;
    end;

    lToast.show;
  end);
end;


No nosso aplicativo de exemplo adicionei um TCheckBox (cbxCustomFont), um novo TColorComboBox (ColorComboBoxText) e um TSpinBox (SpinBoxTextSize), para habilitar a customização de texto selecionando a cor e o tamanho.

E no click do nosso botão ficou:


 
procedure TfrmToastNotification.btnShowToastColorClick(Sender: TObject);
var
  lToastNotification : TToastNotification;
begin
  lToastNotification := TToastNotification.Create;
  try
    lToastNotification.Text := edtText.Text;
    lToastNotification.Duration := TToastLength.LongToast;
    lToastNotification.Color := ColorComboBox.Color;
    lToastNotification.Gravity := TJGravity.JavaClass.AXIS_CLIP or TJGravity.JavaClass.TOP;
    lToastNotification.XOffset := 0;
    lToastNotification.YOffset := 200;
    lToastNotification.MinimumWidth  := 300;
    lToastNotification.MinimumHeight := 150;
    lToastNotification.CustomText := cbxCustomFont.IsChecked;
    lToastNotification.TextColor := ColorComboBoxText.Color;
    lToastNotification.TextSize := SpinBoxTextSize.Value;

    lToastNotification.Show;
  finally
    lToastNotification.Free;
  end;
end;

 

Exemplo de Toast customizado



Plus, adicional, a mais!

 

Incluí uma brincadeira para mostrar as possibilidades do Toast Notification.

Assim como mudamos as propriedades da View do Toast, podemos substituí-la por outra.

Por exemplo podemos usar um JViewCalendar que é uma implementação de Calendário de uma JView e passar ele para o Toast através do método setView.

Criei um método de classe chamado ShowCalendar para exemplificar este caso.


 
class procedure TToastNotification.ShowCalendar(pDate: TDate; pDuration: TToastLength);
var
  lJView: JCalendarView;
begin
  lJView := TJCalendarView.JavaClass.init(TAndroidHelper.Context);
  lJView.setDate(DateTimeToUnix(pDate + 1) * MSecsPerSec);

  CallInUiThread(procedure
  var
    lToast: JToast;
  begin
    lToast := TJToast.JavaClass.init(TAndroidHelper.Context);
    lToast.setView(lJView);
    lToast.SetDuration(TJToast.JavaClass.LENGTH_LONG);
    lToast.show;
  end);
end;
 
Exemplo substituindo a View padrão do Toast por um JCalendarView



Conclusão

Essa brincadeira com Toast Notification surgiu de uma necessidade nossa devido alguns problemas de sincronia que enfrentamos simulando um Toast em nossa aplicação Mobile.

Aqui vai um agradecimento especial ao meu parceirão de programação e sócio Luiz Sfolia, O Radical, que foi quem me mostrou como funcionava o Toast do Android e começou esses ajustes em nosso sistema.  

A seguir deixei um pequeno guia de referência com alguns tipos e métodos que precisei utilizar e seus respectivos uses.

Guia de referência:

TAlphaColor - System.UITypes
StrToJCharSequence - Androidapi.Helpers
JView.setBackgroundColor - Androidapi.JNI.GraphicsContentViewText
StringToJString - Androidapi.JNI.JavaTypes (para suporte inline)
ConvertPointToPixel - FMX.Platform.UI.Android
TPointF - System.Types
DateTimeToUnix - System.DateUtils
MSecsPerSec - System.SysUtils