XE 7 中 Android 下,字符不会触发 OnKeyDown 事件,所以你无法再在编辑框中过滤一些特殊字符,禁止用户输入。虽然 XE7 的TEdit 提供了一个 FilterChar ,但遗憾的是它依然不好。通过分析,其提供了一个 OnValidating 方法在用户输入一个字符时,触发来让您验证输入的有效性。但不幸的是,你在 OnValidating 中修改 Text 的值不会影响显示的效果,个人认为这是一个Bug,问题发生在 FMX.Edit.Style.pas 中:
procedure TStyledEdit.EndIMEInput;
begin
Model.DisableNotify;
try
Model.Text := FTextService.CombinedText;
finally
Model.EnableNotify;
end;
FTextService.Text := FTextService.CombinedText;//此行应为 FTextService.Text:=Model.Text;
FTextService.CaretPosition := Point(GetOriginCaretPosition + FTextService.CombinedText.Length - FTextService.Text.Length, 0);
RepaintEdit;
end;
但修改源码我并不觉得是一个好办法,暂时,我们可以通过异步触发一个事件来修改编辑框的内容:
procedure TForm1.Edit1Validating(Sender: TObject; var Text: string);
var
p,pd,pds:PQCharW;
d,e:Integer;
S:String;
begin
if Length(Text)>0 then
begin
SetLength(S,Length(Text));
p:=PQCharW(Text);
pd:=PQCharW(S);
pds:=pd;
if p^ in ['+','-'] then
begin
Inc(p);
pd^:=p^;
Inc(pd);
end;
d:=0;
e:=0;
while p^<>#0 do
begin
if p^ in ['0'..'9'] then
begin
pd^:=p^;
Inc(pd);
end
else if p^='.' then
begin
Inc(d);
if d=1 then
begin
pd^:=p^;
Inc(pd);
end;
end
else if p^ in ['e','E'] then
begin
Inc(e);
if e=1 then
begin
if d<=1 then
begin
pd^:=p^;
Inc(pd);
end;
end;
end;
Inc(p);
end;
Workers.Post(procedure (AJob:PQJob)
begin
Form1.Edit1.Text:=AJob.ExtData.AsString;
end,TQJobExtData.Create(StrDupX(pds,pd-pds)),True,jdfFreeAsObject);
end;
end;
上面的代码让其只能输入数字,对于非数字的键值将被直接过滤掉。注意,我用到了 QWorker.Post 方法和 QString.StrDupX 函数,您可以替换它们为自己类似的方法,如:在FMX中实现PostMessage的方法。
QString 中提供了一个 FilterCharW 函数和 FilterNoNumberW 函数来提供一些辅助的过滤功能,上面的代码如果用 FilterNoNumberW 可以直接简化为:
procedure TForm1.Edit1Validating(Sender: TObject; var Text: string);
begin
if Length(Text)>0 then
begin
Workers.Post(procedure (AJob:PQJob)
begin
Form1.Edit1.Text:=AJob.ExtData.AsString;
end,TQJobExtData.Create(FilterNoNumberW(Text)),True,jdfFreeAsObject);
end;
end;
