- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试在一个屏幕上使用 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 创建了这个教程。
最佳答案
您可以在一个布局中有多个SurfaceViews
。 Grafika 中的“多表面测试” Activity 有三个。
@nonsleepr 的回答中引用的第一篇文章在 9 个月后跟进了 this post由同一作者撰写,其中提到了 SurfaceView#setZOrderMediaOverlay() 的存在.
要理解的关键是 SurfaceView
不是常规 View 。当您的应用程序出现在前台时,它会获得一个可供绘制的表面。应用程序 UI 中的所有内容都由应用程序呈现到应用程序表面上,然后该表面由系统合成器与其他表面(如状态栏和导航栏)合成。当您创建一个 SurfaceView
时,它实际上是在创建一个由系统而非您的应用合成的全新表面。
您可以非常松散地控制 SurfaceView
表面的 Z 顺序(即“深度”)。有四个位置,从上到下:
SurfaceView
+ ZOrderOnTopSurfaceView
+ ZOrderMediaOverlaySurfaceView
(默认)如果您有两个相同深度的 SurfaceView,并且它们重叠,则结果是不确定的——一个将“获胜”,但您无法控制哪个。
当您有 N 个表面时,现代设备上的系统合成器非常高效。在 N+1 个表面上,您遇到了性能悬崖。因此,虽然您可以拥有三个 SurfaceViews
,但通常最好减少数量。 N 的值因设备而异。
更新:如果您真的想了解 SurfaceView 的工作原理,请参阅 Android System-Level Graphics doc .
关于Android 多个 SurfaceViews,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5647824/
我正在使用两个 MjpegView(扩展 SurfaceView 的自定义 View )构建一个应用程序。问题是有时我看不到第二个摄像机 View ,因为它位于第一个摄像机 View 后面。流媒体工作
我有一个自定义相机应用程序,我希望任何预览尺寸都以全屏模式显示,而不会拉伸(stretch)相机预览图像。为此,我需要使surfaceView 大于屏幕以保持纵横比,因此实际上用户看到的比相机实际捕获
我收到从 SurfaceView.onAttachedToWindow 引发的异常。看起来 SurfaceView 正在尝试引用 mParent,但它是 null。有谁知道为什么不设置父级但会调用 o
我已经将 SurfaceView 子类化并在 Activity 的 onCreate 中实例化它。生成了预览,但控件永远不会进入 onDraw(),它在 SurfaceView 的子类中被重写。这是为
我的应用在 Android 8.0 上遇到了一些奇怪的问题。我有自己的可滚动小部件,代码是 available on github .它有两个 child ,可以无限期地逐一滚动。 在屏幕上,棋盘是一
我用两种方式编写了同一个程序。 一个使用 Surfaceview,另一个使用自定义 View 。根据 android SDK 开发指南,使用表面 View 更好,因为您可以生成一个单独的线程来处理图形
我想做的是 在开始播放视频之前在 SurfaceView 上显示背景图像。 我尝试只绘制一个 jpeg 图像作为 SurfaceView 的背景。有效。 我还尝试在 SurfaceView 上播放视频
我遇到了讨厌的 Android SurfaceView 行为: 当你离开一个带有 SurfaceView 的 Activity 并快速返回时,SurfaceView 之前的内容并没有消失,而是显示在新
我正在创建一个 FrameLayout 类型的布局,我在其中添加了两个 View 。两个 View 分别是 GLSurfaceView 和 SurfaceView 的对象。根据有关 SurfaceVi
我有一个 Activity 调用一个扩展 SurfaceView 并实现 Runnable 的类并将 Activity 类的 contentView() 设置为 surfaceview 类的实例。最小
由于某种原因,我的程序中的摄像头画面是横向的。如果我从底部将手指放在相机上,它会在表面 View 中显示为来自右侧。 我有一个非常标准的实现 surfaceView = (SurfaceVie
我想在我的 SurfaceView 顶部添加一个自定义 ImageButton,这样它基本上可以随 View 滚动。 Canvas 使用矩阵滚动和缩放。我该怎么做呢?谢谢。 最佳答案 假设我正确理解了
在 SurfaceView 上绘图时,我在拦截“后退”按键时遇到问题。我的 onKeyDown 事件似乎只在第二次和随后的按键事件中被调用——这对后退键没有用,因为 Activity 已经暂停或终止。
在我正在进行的项目中,我决定使用 SurfaceView 而不是自定义双缓冲介质。它提供了我需要的一切,而且它已经是双缓冲的。 问题是它不会让我指定多个脏矩形来重绘。 SurfaceView.lock
我正在创建一个小游戏我有一个 Activity : GameActivity.java: public class GameActivity extends Activity { public
这很可能是一件微不足道的事情,但我找不到解决方案。事情很简单,用户按下屏幕,当他的手指放在屏幕上时,我想要执行一段代码。 这是一个代码示例: @Override public boolean
我正在使用 Android SurfaceView 编写测试应用程序。我想看看这是否是一种可行的 2D 游戏开发方法。目前性能不是太好。 似乎每隔 15 秒左右就会出现微小的抖动和减速。我只在屏幕上画
我有一个 SurfaceView,我在其中显示了一个比 SurfaceView 的实际区域大得多的位图,因此我实现了一种方法,让用户可以在位图上滑动手指并上下移动它。这样做时,我希望能够显示垂直滚动条
我正在向 SurfaceView 提供的 Canvas 绘制一些自定义内容。这包含在具有其他 View 的 Activity 中。 我的 Activity 中的一个状态需要隐藏 SurfaceView
所以我在 Android Studio 中做的项目中一直遇到 NullPointerException。我需要让图像显示在我称为 DrawSurface 的自定义类中。我似乎找不到与我的问题相关的任何
我是一名优秀的程序员,十分优秀!