图像在android上无法正确显示
我对Android上的FMX没有正确显示图像有问题 我的应用程序是我第一次使用Android,它有一个背景和一个启动图像,在应用程序启动时显示。飞溅物显示在所有东西的顶部,然后计时器使其消失,并显示背景 Memu emulator的屏幕截图: 我手机上的屏幕截图: 来源于复制的问题: 我从Delphi6开始编写Pascal,在此之前我从未问过任何与编码相关的问题,但这对我来说是非常新的 到目前为止,我已经试了三天让它工作,但没有运气 目前我正在使用图像在android上无法正确显示,android,delphi,bitmap,firemonkey,delphi-xe8,Android,Delphi,Bitmap,Firemonkey,Delphi Xe8,我对Android上的FMX没有正确显示图像有问题 我的应用程序是我第一次使用Android,它有一个背景和一个启动图像,在应用程序启动时显示。飞溅物显示在所有东西的顶部,然后计时器使其消失,并显示背景 Memu emulator的屏幕截图: 我手机上的屏幕截图: 来源于复制的问题: 我从Delphi6开始编写Pascal,在此之前我从未问过任何与编码相关的问题,但这对我来说是非常新的 到目前为止,我已经试了三天让它工作,但没有运气 目前我正在使用RCDATA资源并从那里加载图像。我甚至尝
RCDATA
资源并从那里加载图像。我甚至尝试将图像放在不同的形式上,就像其他TImage
组件一样,然后从那里加载。我还注意到,如果图像被设置为Align=Client
,并且WrapMode=Center
,那么它们都会被错误地放置在MainForm
上,但在其他表单上工作得很好。所以现在,我尝试裁剪图像,它们是正方形的,这样它们的纵横比就和它运行的设备一样
我可以继续说下去,因为到目前为止我试过的是一场长谈
procedure TForm1.FormShow(Sender: TObject);
var
Bmp, BmpSplash: TBitmap;
iRect: TRect;
begin
Load_image_from_resource(Form1.Image_bg, '0_bg');
Load_image_from_resource(Form1.Image_splash, '0_splash');
Bmp := TBitmap.Create;
try
Bmp.Width := round(Form1.Image_bg.Bitmap.Width * (Form1.ClientWidth / Form1.ClientHeight));
Bmp.Height := round(Form1.Image_bg.Bitmap.Height);
iRect.Width := round(Form1.Image_bg.Bitmap.Width * (Form1.ClientWidth / Form1.ClientHeight));
iRect.Height := Bmp.Height;
iRect.Left := round((iRect.Height - iRect.Width) / 2);
iRect.Top := 0;
Bmp.CopyFromBitmap(Form1.Image_bg.Bitmap, iRect, 0, 0);
//Form1.Image_bg.Bitmap := nil;
Form1.Image_bg.Bitmap.Assign(Bmp);
Form1.Image_bg.Align := TAlignLayout.Client;
Form1.Image_bg.WrapMode := TImageWrapMode.Stretch;
finally
Bmp.DisposeOf;
Bmp := nil;
end;
BmpSplash := TBitmap.Create;
try
BmpSplash.Width := round(Form1.Image_splash.Bitmap.Width * (Form1.ClientWidth / Form1.ClientHeight));
BmpSplash.Height := round(Form1.Image_splash.Bitmap.Height);
iRect.Width := round(Form1.Image_splash.Bitmap.Width * (Form1.ClientWidth / Form1.ClientHeight));
iRect.Height := Bmp.Height;
iRect.Left := round((iRect.Height - iRect.Width) / 2);
iRect.Top := 0;
BmpSplash.CopyFromBitmap(Form1.Image_splash.Bitmap, iRect, 0, 0);
//Form1.Image_splash.Bitmap := nil;
Form1.Image_splash.Bitmap.Assign(BmpSplash);
Form1.Image_splash.Align := TAlignLayout.Client;
Form1.Image_splash.WrapMode := TImageWrapMode.Stretch;
finally
BmpSplash.DisposeOf;
BmpSplash := nil;
end;
Form1.Image_bg.SendToBack;
Form1.Image_bg.Visible := False;
Form1.Image_splash.BringToFront;
Form1.Image_splash.Visible := True;
Form1.Timer1.Enabled := True;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Form1.Timer1.Enabled := False;
Form1.Image_bg.Visible := True;
Form1.Image_splash.Visible := False;
end;
您非常接近,我认为Delphi代码中的以下特性可能让您最头疼: 在代码中有如下内容:
iRect.Width := ...
iRect.Height := ...
iRect.Left := ...
iRect.Top := ...
TRect
(或TRectF
)由其四个属性决定:左、上、右、下。
当您使用宽度
(和高度
)更改尺寸时,可将此设置程序称为:
// This is the code in XE7, I do not know if it has been changed later
procedure TRect.SetWidth(const Value: Integer);
begin
Self.Right := Self.Left + Value;
end;
SetHeight
非常相似
当您更改左侧
或顶部
时,只需更改相应的字段,但不会更改右侧
或底部
。结果是宽度
或高度
也会改变
设想一个本地未初始化变量direct
,它可能具有Left
和Right
的任何值。上面的代码可能会以非常奇怪的TRect
矩形结束。解决方法是首先设置左
和顶
属性,然后设置右
和顶
或宽度
和高度
要显示图像,您要求它遵循纵横比,这意味着垂直显示图像时需要从图像的侧面(水平显示时从顶部和底部)剪切切片。我使用direct
进行了此操作,以便将其初始化为屏幕大小,然后用屏幕大小和图像大小之间的差值的一半进行偏移
下面是根据屏幕大小显示图像的代码。这里只有垂直显示,但水平显示将遵循相同的方案。为了简洁起见,我也没有包括splash图像,请使用相同的代码和您自己的更改逻辑。代码中的注释应该可以解释我的想法。正如您看到的,它与您的非常相似,您对direct.Width
和direct.Left
的计算不正确,可能是因为TRect
的特性
// I feel more comfortable with a bmp as temporary storage than the TImage, therefore this minor mod
procedure Load_Bitmap_From_Resource(var bmp: TBitmap; res_name: String);
var InStream: TResourceStream;
begin
InStream := TResourceStream.Create(HInstance, res_name, RT_RCDATA);
try
Bmp.LoadFromStream(InStream);
finally
InStream.Free;
end;
end;
procedure TForm1.FormShow(Sender: TObject);
var
ScrHeight, ScrWidth: integer;
bmp, bmp2, BmpSplash: TBitmap;
iRect: TRect;
begin
// Form1 acted for me also as a simulation form during dev, therefore
// these settings are not meant to be included in actual application
// ***********
self.Left := 0; self.ClientWidth := 270;
self.Top := 0; self.ClientHeight := 540;
// ***********
// Use FireMonkey Platform Services, IFMXScreeService to get real size of screen
ScrHeight := 2160; // just arbitrary examples, ..
ScrWidth := 1080; // ..for testing use size of your own phone
// I feel more comfortable with a bmp as temporary storage than the TImage
bmp := TBitmap.Create;
try
Load_Bitmap_From_Resource(bmp, '0_bg');
iRect := Rect(Point(0, 0), Point(ScrWidth, ScrHeight));
iRect.Offset((bmp.Width-ScrWidth) div 2, (bmp.Height-ScrHeight) div 2);
bmp2 := TBitmap.Create;
try
bmp2.SetSize(iRect.Width, iRect.Height);
bmp2.CopyFromBitmap(bmp, iRect, 0, 0);
Form1.Image_bg.Bitmap.Assign(bmp2);
Form1.Image_bg.Align := TAlignLayout.Client;
finally
bmp2.DisposeOf;
end;
finally
bmp.DisposeOf;
end;
Form1.Image_bg.Visible := True;
end;
谢谢你的语法编辑,Remy:-)我发现你的代码有几个问题,但你还没有表达你希望在各种情况下,如水平/垂直不同的显示分辨率等,飞溅图像和背面图像显示的准确程度。请编辑并添加信息。如果我不够清楚,我很抱歉,我尽量不深入细节,因为否则你会读一整本书:-)我希望启动应用程序时显示飞溅图像,几秒钟后它应该消失,背景显示,直到用户关闭应用程序。我提供的源代码只是我尝试过的东西之一,它检测屏幕大小,如果是纵向的,那么它将使用我在这里提供的代码。我没有做过横向,因为我不想在没有另一个先工作的情况下做得更进一步。如前所述,如果我的TImage为align:=client和wrapmode:=center,那么它会将图像放错位置,但不会放在其他表单上。我开始认为这可能是某种内存问题,或者更多的是我不知道的android的局限性,因为当我编译成这样时,它在win32+64上运行良好。我真的希望有人能帮我,因为我开始失去理智了:-)好的,我在考虑分辨率,因为源图像是2160 x 2160。简单的解决方案是根据需要拉伸以适应显示,但会改变文本的外观。可以吗?如果长宽比根据物理显示而变化,这与此无关吗?还有其他要求吗?您还没有说过吗?非常感谢!我只是在我制作的示例/复制代码上尝试了它,它确实起了作用。所以,现在我正在尝试将其实现到我的应用程序中,如果它有效,我将与您联系;-)虚惊一场。。它在Memu emulator上运行,然后我尝试在我的应用程序上实现它,但随后我也在Memu中编译并尝试了它,然后它冻结了一些过程。然后我试了试我的手机,然后它甚至都没有安装。“应用程序未安装。”,它说。然后我试着用你的代码在我的手机上安装我制作的测试应用程序,但也无法安装,因为它给了我同样的信息。为了正确编译Android应用程序,我需要做些什么吗?我开始认为编译器或其他东西可能是问题所在,因为我不明白它应该那么脆弱。德尔福从来没有像我这样不稳定过-/请注意,问答网站也是如此,可以回答特定的问题。它不是一个正在进行的调试服务。您的具体问题是如何修复代码以正确显示背景图像和飞溅图像,而不是问题中显示的错误裁剪图像。我指出了错误