- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个带有自定义 SurfaceView 类和一些按钮的简单 LinearLayout。以前我在 Manifest 的 Activity 标签中强制将方向设置为 Landscape,但现在我需要将其设置为纵向。出于某种原因,当我强制使用方向肖像时,不会创建 SurfaceView。我通过仅使用单个 FrameLayout 并在其中使用我的 SurfaceView 类的单个实例来测试布局,但它仍然无法正确创建。
我得到的错误取决于 SurfaceView 中 Thread 的第一个实例是什么。通常是我的 UI 线程在 onCreate 中请求线程句柄导致 NullPointerException。
知道为什么我的代码可以横向运行而不是纵向运行吗?如果我不选择方向然后将其从横向旋转为纵向,也会出现同样的问题。
编辑:这是我的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<stu.test.project.DrawingSurface
android:layout_width="fill_parent"
android:layout_height="700dp"
android:id="@+id/drawingSurface"/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:id="@+id/ButtonRow1"/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:id="@+id/ButtonRow2"/>
</LinearLayout>
</LinearLayout>
这里是调用surfaceView的Activity的onCreate,错误位于最后一行获取线程句柄的地方
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.drawing_layout);
// Retrieve STATE and patient number from intent
bundle = this.getIntent().getExtras();
STATE = bundle.getInt("state");
patientString = bundle.getString("patientString");
//retrieveViews();
showButtons();
System.out.println("IN ONCREATE");
// Setup initial stuff if creating rather than resuming
if (savedInstanceState==null){
System.out.println("IN ONCREATE AND NO SIS");
switch(STATE){
case STATE_DRAW:
setupDraw();
break;
case STATE_LOAD:
setupLoad();
drawLoad();
break;
}
}
/* Should put Else in here
* to maybe resume data from savedInstanceState
* rather than using onSurfaceCreated as do at moment
*/
// Retrieve handle to thread
mThread = drawingSurface.getThread();
}
这里是 SurfaceView 类,不确定什么是相关的所以全部复制:
public class DrawingSurface extends SurfaceView implements SurfaceHolder.Callback {
private boolean _run;
private Object mPauseLock = new Object();
private boolean mPaused;
private int STATE;
private static final int STATE_DRAW=1;
private static final int STATE_LOAD=2;
private static final int STATE_PAUSED=4;
private static final int STATE_RESUME_DRAWING=5;
private boolean finishDrawing;
private boolean startedDrawing=true;
private int resetCanvas=0;
private boolean threadRunning;
protected DrawThread thread;
boolean loaded;
public DrawingSurface(Context context, AttributeSet attrs) {
super(context, attrs);
getHolder().addCallback(this);
thread = new DrawThread(getHolder());
}
class DrawThread extends Thread{
private SurfaceHolder mSurfaceHolder;
private List<DrawingPath> mDrawingPaths;
private List<MyLine> mMyLines, backupLines;
private Paint mPaint;
public DrawThread(SurfaceHolder surfaceHolder){
mSurfaceHolder = surfaceHolder;
mDrawingPaths = Collections.synchronizedList(new ArrayList<DrawingPath>());
mMyLines = Collections.synchronizedList(new ArrayList<MyLine>());
}
public void setRunning(boolean run) {
_run = run;
}
public void setBackupLine(List<MyLine> l){
backupLines = l;
System.out.println("SETUP BACKLINE SIZE IS: "+backupLines.size());
}
// Two methods for your Runnable/Thread class to manage the Thread properly.
public void onPause() {
synchronized (mPauseLock) {
// Only pause if not finished drawing, if finished want to exit thread
if (!finishDrawing){
mPaused = true;
loaded=false;
}
}
System.out.println("Set mPaused = true");
}
public void onResume() {
synchronized (mPauseLock) {
mPaused = false;
mPauseLock.notifyAll();
}
System.out.println("Set mPaused = false");
// // Load the saved drawings or reload
// if (STATE == STATE_DRAW)
// setState(STATE_RESUME_DRAWING);
// // If loading then dont change state and instead just restart thread
// else if (STATE == STATE_LOAD){
//// resumeDrawing();
// setRunning(true);
// }
}
public boolean needToWait(){
return finishDrawing||mPaused;
}
public void setFinishDrawing(boolean b){
finishDrawing=b;
}
public void setReset(int reset){
resetCanvas=reset;
}
public void addMyLines(List<MyLine> lines){
mMyLines = lines;
}
public void addDrawingPath(DrawingPath drawingPath){
mDrawingPaths.add( drawingPath );
}
public int getSizeDrawingPaths(){
return mDrawingPaths.size();
}
public void setLoadPaint(Paint p){
mPaint = p;
}
public DrawingPath getDrawingPath(int index){
return mDrawingPaths.get(index);
}
@Override
public void run() {
while (_run){
// Set variable for running
threadRunning=true;
Canvas canvas = null;
// This code pauses the thread
synchronized (mPauseLock) {
while (mPaused) {
try {
mPauseLock.wait();
System.out.println("IN PAUSE LOOP");
} catch (InterruptedException e) {
}
}
}
try{
canvas = mSurfaceHolder.lockCanvas(null);
// Split into DRAW and LOAD
// DRAW IMAGE FROM PATHS
if (STATE == STATE_DRAW){
synchronized(mDrawingPaths) {
// If not finished drawing or resetthen draw onto canvas
if (!finishDrawing&&resetCanvas==0){
// // Draw screen white
// if (startedDrawing){
// startedDrawing=false;
// canvas.drawColor(Color.WHITE);
// System.out.println("DRAWING CANVAS WHITE");
//
// }
doDraw(canvas);
}
}
if (resetCanvas>0){
System.out.println("Resetting canvas");
if (canvas!=null)
canvas.drawColor(Color.WHITE);
resetCanvas--;
}
}
// DRAW IMAGE FROM POINTS
else if (STATE == STATE_LOAD){
doLoad(canvas, mMyLines);
// Then close the thread
setRunning(false);
}
// IF RESUMING FROM DRAWING PAUSE
else if (STATE == STATE_RESUME_DRAWING){
if (!loaded) {
doLoad(canvas, backupLines);
System.out.println("DID LOAD OF RESUME");
setState(STATE_DRAW);
loaded=true;
//setRunning(false);
}
}
}
finally {
if (canvas!=null){
mSurfaceHolder.unlockCanvasAndPost(canvas);
}
}
} // While run
}
public void doDraw(Canvas c){
@SuppressWarnings("rawtypes")
Iterator i = mDrawingPaths.iterator();
while (i.hasNext()){
final DrawingPath drawingPath = (DrawingPath) i.next();
if (c==null)
System.out.println("CANVAS IS NULL");
else if (drawingPath.path==null)
System.out.println("PATH IS NULL");
else if (drawingPath.paint==null)
System.out.println("PAINT IS NULL");
if (c!=null) // Only draw to canvas if it isnt null
c.drawPath(drawingPath.path, drawingPath.paint);
}
}
public void doLoad(Canvas c, List<MyLine> lines){
// Loop through the List of lines
@SuppressWarnings("rawtypes")
Iterator i = lines.iterator();
while(i.hasNext()){
// Get the current line
final MyLine lineIt = (MyLine) i.next();
// Create new array of floating points to hold the PointFs from MyLine to draw
float prevX=0, prevY=0;
for (int j=0;j<lineIt.getSize()-1;j=j+2){
if (c==null)
System.out.println("CANVAS IS NULL");
if (j!=0&&c!=null){
c.drawLine(prevX, prevY, lineIt.getPoint(j).x, lineIt.getPoint(j+1).y, mPaint);
}
prevX = lineIt.getPoint(j).x;
prevY = lineIt.getPoint(j+1).y;
}
}
}
public void remove(int i) {
mDrawingPaths.remove(i);
}
public void clearAllPaths(){
mDrawingPaths.clear();
}
public void setState(int s){
STATE = s;
}
}
public void addDrawingPath (DrawingPath drawingPath){
thread.addDrawingPath(drawingPath);
}
public int getSizeDrawingPaths(){
return thread.getSizeDrawingPaths();
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
// only create thread if doesnt exist
if (!threadRunning){
thread.setRunning(true);
thread.setFinishDrawing(false);
thread.setReset(2); // Set reset to colour screen white
thread.start();
}
// // Resuming is handled in DrawingActivity's onPause override
// else {
// thread.onResume();
// }
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
boolean retry = true;
// If finished drawing then close thread
// Else just want to pause thread
// if (finishDrawing){
// thread.setRunning(false);
// while (retry) {
// try {
// thread.join();
// retry = false;
// threadRunning = false; // Set threadRunning to false so creates new thread when rejoins
// } catch (InterruptedException e) {
// // we will try it again and again...
// }
// }
// }
// else {
// thread.onPause();
// System.out.println("Paused thread in SurfaceDestroyed");
// System.out.println("threadRunning is :"+threadRunning);
// }
}
public void remove(int i) {
thread.remove(i);
}
public void getDrawingPath(int i){
thread.getDrawingPath(i);
}
public void clearAllPaths(){
thread.clearAllPaths();
}
public void resetScreen(){
thread.setReset(2);
}
public void addMyLines(List<MyLine> lines){
thread.addMyLines(lines);
}
public void finishDrawing(){
thread.setFinishDrawing(true);
}
public DrawThread getThread(){
return thread;
}
public void resumeDrawing(){
thread.setFinishDrawing(false);
}
public void setState(int s){
thread.setState(s);
}
public void setLoadPaint(Paint p){
thread.setLoadPaint(p);
}
public void pauseThread(){
thread.onPause();
}
public void resumeThread(){
thread.onResume();
}
public boolean getThreadRunning(){
return threadRunning;
}
}
最佳答案
纵向和横向是否有相同的布局文件?
今天我遇到了一个类似的问题,我在纵向布局文件中有 surfaceView,但在横向布局文件中没有。由于某种原因它运行了但是当我旋转设备时 surfaceCreated|Changed|Destroyed 不再发生。旋转回来,一切又是快乐的。
关于Android SurfaceView 不在纵向模式下创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8746693/
我正在使用两个 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 的自定义类中。我似乎找不到与我的问题相关的任何
我是一名优秀的程序员,十分优秀!