gpt4 book ai didi

Android 多个 SurfaceViews

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:29:53 25 4
gpt4 key购买 nike

我正在尝试在一个屏幕上使用 3 个 SurfaceView,一个在上半部分 (BoardView),一个在下半部分 (StatusView),最后一个作为上半部分 (TileView) 之上的额外层(参见 main .xml)。

我创建了一个类 MySurfaceView,它由 BoardView、StatusView 和 TileView 扩展。

我遇到了很多问题。

我先给出代码

主.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/main_background">

<com.niek.test.BoardView
android:id="@+id/boardview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="@+id/boardview">
<com.niek.test.StatusView
android:id="@+id/statusview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#F0931E"
android:layout_below="@+id/boardview" />

<com.niek.test.TileView
android:id="@+id/tileview"
android:layout_width="180dip"
android:layout_height="60dip"
android:layout_gravity="bottom"/>


</FrameLayout>
</RelativeLayout>

主要 Activity .java:

package com.niek.test;

public class MainActivity extends Activity {

private Board board;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

board = new Board();
BoardView boardView = (BoardView) findViewById(R.id.boardview);
boardView.setBoard(board);
StatusView statusView = (StatusView) findViewById(R.id.statusview);
statusView.setBoard(board);
}
}

MySurfaceView.java

package com.niek.test;

public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {

protected DrawThread drawThread;

public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
getHolder().addCallback(this);
setFocusable(true);

drawThread = new DrawThread(getHolder());
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub

}

@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
drawThread.setRunning(true);
drawThread.start();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// we have to tell thread to shut down & wait for it to finish, or else
// it might touch the Surface after we return and explode
boolean retry = true;
drawThread.setRunning(false);
while (retry) {
try {
drawThread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}

protected class DrawThread extends Thread {
private SurfaceHolder surfaceHolder;
private boolean isRunning;

public DrawThread(SurfaceHolder surfaceHolder) {
this.surfaceHolder = surfaceHolder;
isRunning = false;
}

public void setRunning(boolean run) {
isRunning = run;
}

public void run() {
Canvas c;
while (isRunning) {
try {
Thread.sleep(100);
} catch (Exception e) {
// TODO: handle exception
}
c = null;
try {
c = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder) {
onDraw(c);
postInvalidate();
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}

}

这三个类扩展了 MySurfaceView:

板 View .java

package com.niek.test;


public class BoardView extends MySurfaceView {

private int squareSize, marginX, marginY;

private Board board;

Paint boardBorder;

public BoardView(Context context, AttributeSet attrs) {
super(context, attrs);
board = null;
}

public void setBoard(Board board) {
this.board = board;
}

private void init(SurfaceHolder holder) {
Canvas canvas = null;
try {
canvas = holder.lockCanvas();
/* Initialize the board */
squareSize = canvas.getWidth() / Board.GRIDSIZE;

/* Size the view */
LayoutParams lp = getLayoutParams();
lp.height = (squareSize * Board.GRIDSIZE) + 4;
setLayoutParams(lp);

/* Place the board neatly in the center */
marginX = (canvas.getWidth() - (squareSize * Board.GRIDSIZE)) / 2;
marginY = 1;
} finally {
holder.unlockCanvasAndPost(canvas);
}

boardBorder = new Paint();
boardBorder.setColor(Color.RED);
boardBorder.setStyle(Style.STROKE);
}

@Override
public void onDraw(Canvas canvas) {
drawBoard(board, canvas);
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
init(holder);
super.surfaceCreated(holder);
}

private void drawBoard(Board board, Canvas canvas) {
synchronized (board) {
if (board != null) {
for (Square[] ys : board.getSquares()) {
for (Square xs : ys) {
xs.onDraw(canvas, squareSize, squareSize, marginX, marginY);
}
}
}
canvas.drawRect(marginX - 1, marginY - 1, marginX + squareSize * Board.GRIDSIZE + 1, marginY + squareSize * Board.GRIDSIZE + 1, boardBorder);
}
}
}

状态 View .java

package com.niek.test;

public class StatusView extends MySurfaceView {

private Board board;
private Paint textPaint;

public StatusView(Context context, AttributeSet attrs) {
super(context, attrs);
board = null;

textPaint = new Paint();
textPaint.setColor(Color.BLACK);
textPaint.setTextSize(20);
textPaint.setTypeface(Typeface.DEFAULT_BOLD);
}

public void setBoard(Board board) {
this.board = board;
}

int tmp=0;
@Override
public void onDraw(Canvas c) {
if (board != null) {
c.drawText(tmp+"", 10, 20, textPaint);
tmp++;
System.out.println(tmp);
}
}
}

TileView.java

package com.niek.test;

public class TileView extends MySurfaceView {

public TileView(Context context, AttributeSet attrs) {
super(context, attrs);
System.out.println(0);
}


int tmp =0;
@Override
public void onDraw(Canvas c) {
System.out.println(2);
Paint p= new Paint();
p.setColor(Color.RED);
c.drawColor(Color.RED);
c.drawText(tmp+"",10,10,p);
tmp++;

}

}

现在我的问题是什么?

首先,正如您在 MySurfaceView 中看到的那样,我得到了这个:

try {
c = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder) {
onDraw(c);
postInvalidate();
}
}

当我只使用 onDraw(c) 时,只绘制了 BoardView,不绘制 StatusView,但正在执行 StatusView 的 onDraw 中的 tmp 增量。当我只使用 postInvalidate() 时,情况相同,但只绘制 StatusView,而 BoardView 不绘制。这就是我使用这两种方法并绘制两个 View 的原因。

然后是 TileView,Logcat 中显示了 System.out(2),但未绘制 View 。它是一个黑色方 block 而不是我要求它在 onDraw 方法中的红色方 block 。

当我关闭屏幕然后再次打开时,会绘制 TileView,并显示 tmp 增量。

谁能帮帮我?

为了清楚起见,我根据 this 创建了这个教程。

最佳答案

可以在一个布局中有多个SurfaceViewsGrafika 中的“多表面测试” Activity 有三个。

@nonsleepr 的回答中引用的第一篇文章在 9 个月后跟进了 this post由同一作者撰写,其中提到了 SurfaceView#setZOrderMediaOverlay() 的存在.

要理解的关键是 SurfaceView 不是常规 View 。当您的应用程序出现在前台时,它会获得一个可供绘制的表面。应用程序 UI 中的所有内容都由应用程序呈现到应用程序表面上,然后该表面由系统合成器与其他表面(如状态栏和导航栏)合成。当您创建一个 SurfaceView 时,它实际上是在创建一个由系统而非您的应用合成的全新表面。

您可以非常松散地控制 SurfaceView 表面的 Z 顺序(即“深度”)。有四个位置,从上到下:

  • SurfaceView + ZOrderOnTop
  • (此处为应用界面)
  • SurfaceView + ZOrderMediaOverlay
  • SurfaceView(默认)

如果您有两个相同深度的 SurfaceView,并且它们重叠,则结果是不确定的——一个将“获胜”,但您无法控制哪个。

当您有 N 个表面时,现代设备上的系统合成器非常高效。在 N+1 个表面上,您遇到了性能悬崖。因此,虽然您可以拥有三个 SurfaceViews,但通常最好减少数量。 N 的值因设备而异。

更新:如果您真的想了解 SurfaceView 的工作原理,请参阅 Android System-Level Graphics doc .

关于Android 多个 SurfaceViews,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5647824/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com