我在DELPHI 12中编写了一个用于SurfaceView绘画的Android应用程序。SurfaceView始终显示黑色背景,没有任何画笔的痕迹。以下是完整代码,请帮我找出问题所在。谢谢。
定义类TMySurfaceView_callback来实现JSurfaceHolder_Callback接口,并定义jpaint、jpath和JSurfaceHolder类型成员变量以供后续操作。 在TMySurfaceView_callback的构造方法中,使用TJSurfaceView.JavaClass.init(TAndroidHelper.Context)直接构造SurfaceView实例,并设置TMySurfaceView_callback实例的jpaint、jpath和JSurfaceHolder类型成员变量。 构建 TJFrameLayout_LayoutParams 布局并将 SurfaceView 添加到 TAndroidHelper.Activity.addContentView(Surfaceview, LayoutParams) 程序窗口。 在 TMySurfaceView_callback.SurfaceCreated(holder: JSurfaceHolder) 中绘制。获取画布并调用draw方法。事实上,进入这个方法后,SurfaceView只显示黑色背景,进入线程执行后也是如此。 我还为表面视图设置了一个触摸监听器。通过监听器,我认为surfaceview构建成功了。 但为什么总是显示黑色呢?画笔的绘画结果未显示。
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,Androidapi.Helpers,
Androidapi.JNI.GraphicsContentViewText, FMX.Helpers.Android, FMX.Surfaces
, Androidapi.JNI.App,androidapi.JNIBridge,Androidapi.JNI.JavaTypes,
FMX.Controls.Presentation, FMX.StdCtrls, FMX.Layouts,Androidapi.JNI.Embarcadero,
Androidapi.JNI.Widget,FMX.Objects,fmx.Platform.Android,fmx.Platform,
FMX.ListView.Types, FMX.ListView.Appearances, FMX.ListView.Adapters.Base,
FMX.ListView, Androidapi.JNI.Os;
type
TForm1 = class(TForm)
Button1: TButton;
GridPanelLayout1: TGridPanelLayout;
Layout1: TLayout;
Layout2: TLayout;
Image1: TImage;
Button2: TButton;
ListView1: TListView;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TMySurfaceView_callback = class(TJavaLocal, JSurfaceHolder_Callback)
private
FSurfaceHolder: JSurfaceHolder;
paint:jPaint;
count:integer;
mPath:jpath;
isDraw:boolean;
public
constructor Create;
procedure Release;
procedure SurfaceChanged(holder: JSurfaceHolder; format: Integer; width, height: Integer); cdecl;
procedure SurfaceCreated(holder: JSurfaceHolder); cdecl;
procedure SurfaceDestroyed(holder: JSurfaceHolder); cdecl;
procedure draw;
procedure moveTo(x,y:single);
procedure quadTo(x,y,w,h:single);
end;
myView_OnTouchListener = class(TJavaLocal,JView_OnTouchListener)
public
constructor Create;
function onTouch(v: JView; event: JMotionEvent ) :boolean;cdecl;//override;
// function onTouchEvent(event: jMotionEvent): boolean;
end;
var
Form1: TForm1;
SurfaceView: jSurfaceView;
mythread:tmythread;
implementation
{$R *.fmx}
{$R *.LgXhdpiPh.fmx ANDROID}
{$R *.LgXhdpiTb.fmx ANDROID}
uses FMX.Graphics.Android;
{ TMySurfaceView }
constructor TMySurfaceView_callback.Create;
var
LayoutParams: JFrameLayout_LayoutParams;
SurfaceFrameLayout:jframelayout;
myView_OnTouchListener1:myView_OnTouchListener;
begin
inherited Create;
SurfaceView := TJSurfaceView.JavaClass.init(TAndroidHelper.Context);
FSurfaceHolder := Surfaceview.getHolder;
FSurfaceHolder.addCallback(Self);
FSurfaceHolder.setKeepScreenOn(true);
SurfaceView.setVisibility(0);
SurfaceView.setFocusable(true);
SurfaceView.setFocusableInTouchMode(true);
SurfaceView.setKeepScreenOn(true);
// surfaceView.getHolder.setFormat(-2); //-3 半透明
surfaceView.setzOrderOnTop(true);
myView_OnTouchListener1:=myView_OnTouchListener.Create;
Surfaceview.setOnTouchListener(myView_OnTouchListener1 );
LayoutParams := TJFrameLayout_LayoutParams.JavaClass.init(800,1000);
LayoutParams.topMargin:=500;
LayoutParams.leftMargin:=200;
TAndroidHelper.Activity.addContentView(Surfaceview, LayoutParams) ;
mpath:=tjpath.JavaClass.init;
paint:=TJPaint.JavaClass.init;
paint.setColor($FF0000);
paint.setStrokeWidth(57);
paint.setStyle(TJPaint_Style.JavaClass.FILL_AND_STROKE);
paint.setTextSize(50);
paint.setTextAlign(TJpaint_align.JavaClass.CENTER);
end;
procedure TMySurfaceView_callback.draw;
var
Canvas: JCanvas;
NewThread: TThread;
begin
// while isDraw do
begin
NewThread := TThread.CreateAnonymousThread(
procedure
begin
TRY
count:=count+1;
Canvas := FSurfaceHolder.lockCanvas;
Canvas.drawColor($FA8072,TJPorterDuff_Mode.JavaClass.clear) ;
Canvas.drawCircle(100,100,100,paint);
Canvas.drawCircle(200,200,20,paint);
Canvas.drawText(stringtoJstring('canvas text:--'+inttostr(count)),500,300,paint) ;
Canvas.drawPath(mPath, Paint);
TThread.Synchronize(nil,
procedure
begin
// 更新UI组件
form1.Button2.Text:='Runing...';
end
);
finally
FSurfaceHolder.unlockCanvasAndPost(Canvas);
end;
end
);
NewThread.FreeOnTerminate := True; // 确保线程执行完毕后自动释放资源
NewThread.Start; // 启动新线程
end
end;
procedure TMySurfaceView_callback.moveTo(x, y: single);
begin
mPath.moveTo(x, y);
end;
procedure TMySurfaceView_callback.quadTo(x, y, w, h: single);
begin
mPath.quadTo(x, y, (x + w) / 2, (y + h) / 2);
end;
procedure TMySurfaceView_callback.Release;
begin
FSurfaceHolder.removeCallback(Self);
inherited;
end;
procedure TMySurfaceView_callback.SurfaceChanged(holder: JSurfaceHolder; format, width, height: Integer);
var
Canvas: JCanvas;
begin
// showmessage('SurfaceChanged');
end;
procedure TMySurfaceView_callback.SurfaceCreated(holder: JSurfaceHolder);
var
Canvas: JCanvas;
bmp:jbitmap;
begin
// 获取画布并绘制内容
showmessage('SurfaceCreated');
if not (FSurfaceHolder.getSurface.isValid) then
begin
showmessage('播放器设置或销毁显示区域失败!');
end;
isDraw:=true;
bmp:=tjbitmap.JavaClass.createBitmap(800,1000,TJBitmap_Config.JavaClass.ARGB_8888);
bmp.eraseColor($FA8072);
Canvas := FSurfaceHolder.lockCanvas;
Canvas.drawBitmap(bmp,0,0,paint);
// Canvas.drawColor($FA8072) ;
FSurfaceHolder.unlockCanvasAndPost(Canvas);
draw;
end;
procedure TMySurfaceView_callback.SurfaceDestroyed(holder: JSurfaceHolder);
begin
// 释放资源
showmessage('SurfaceDestroyed');
isDraw:=false;
end;
// 在你的TSurfaceView的事件中使用TCustomCanvas来绘制动画
procedure TForm1.Button1Click(Sender: TObject);
// 使用TMySurfaceView
var
MySurfaceView: TMySurfaceView_callback;
begin
MySurfaceView := TMySurfaceView_callback.Create;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
// TSurfaceView.mSurfaceHolder_Callback.isDraw:=false;
end;
{ myView_OnTouchListener }
constructor myView_OnTouchListener.Create;
begin
inherited Create;
end;
function myView_OnTouchListener.onTouch(v: JView;event: jMotionEvent): boolean;
var
x,y,dx,dy,mLastX,mLasty:single;
begin
form1.ListView1.items.Clear;
x := event.getX;
y := event.getY;
// showmessage('touch me at x,y: '+FloatToStr(x)+','+FloatToStr(y));
case (event.getAction) of
0: //tjMotionEvent.JavaClass.ACTION_DOWN TSurfaceView.
begin
mLastX := x;
mLastY := y;
// TMySurfaceView_callback.moveTo(mLastX, mLastY);
end;
2: //tjMotionEvent.JavaClass.ACTION_MOVE
begin
dx :=abs(x - mLastX);
dy := abs(y - mLastY);
if (dx >= 3) and (dy >= 3) then
// TMySurfaceView_callback.quadTo(mLastX, mLastY, (mLastX + x) / 2, (mLastY + y) / 2);
mLastX := x;
mLastY := y;
form1.ListView1.items.Add.Text:='X:'+FloatToStr(x)+','+ 'y:'+FloatToStr(y)
end;
1: //tjMotionEvent.JavaClass.ACTION_UP
;
end;
result:=true;
end;
end.
这就是解决方案 编辑-->
paint.setStyle(TJPaint_Style.JavaClass.FILL_AND_STROKE);
到 --->
paint.setStyle(TJPaint_Style.JavaClass.FILL);