2011-04-25 44 views
7

Giống như nhiều người khác, tôi đang cố gắng vẽ các đối tượng 3D (sử dụng GLSurfaceView) trên xem trước máy ảnh (sử dụng SurfaceView), cùng với một số nút được đặt ở trên cùng. Tôi thực sự có một nguyên mẫu làm việc, nhưng tôi không thể làm cho onResume hoạt động chính xác. Sau khi tiếp tục, GLSurfaceView vẫn ở lại và không hiển thị nữa. Tôi biết rằng nó đang làm việc, bởi vì tôi có thể thấy các bản vẽ tốt nếu tôi loại bỏ các SurfaceView từ bố trí.Cách sử dụng đúng setZOrderMediaOverlay trên Android?

Mục tiêu là Nexus One, chạy ROM 2.3.3.

Đây là xml bố trí:

<com.example.cameratest.GLPreview 
     android:id="@+id/cubes" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent"/> 

<com.example.cameratest.Preview 
     android:id="@+id/camera" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent"/> 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/buttongroup" 
    android:orientation="vertical" 
    android:layout_width="wrap_content" 
    android:layout_height="fill_parent" 
    android:layout_gravity="right" android:gravity="center"> 

    <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:id="@+id/buttonClose"></Button> 
    <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:id="@+id/buttonMode"></Button>  
    <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:id="@+id/buttonCameraInfo"></Button> 
</LinearLayout> 

Tất cả điều này được bọc trong một khối <merge>, nhưng đối với một số lý do, tôi không thể bao gồm nó trong <code> niêm yết trên. Preview là lớp mở rộng SurfaceView và triển khai logic xem trước máy ảnh.

Điều này hoạt động tốt khi hoạt động khởi chạy. Sau khi tôi khởi động một hoạt động khác (ví dụ, bằng cách nhấn một trong các nút) và kết thúc hoạt động đó, hoạt động chính sẽ tiếp tục nhưng các đối tượng 3D sẽ không hiển thị nữa.

Tôi tìm thấy this discussion nơi được đề cập rằng setZOrderMediaOverlay() sẽ giúp khắc phục vấn đề đặt hàng z này. Ngoài ra, các Android document for setZOrderMediaOverlay() nói rằng chức năng này nên được gọi là "trước khi cửa sổ có chứa xem bề mặt được gắn vào trình quản lý cửa sổ". Tôi không biết làm thế nào tôi nên giải thích rằng tuyên bố, vì vậy tôi đặt các báo cáo gỡ lỗi trong mã để xem chuỗi các sự kiện. Dưới đây là cách mã GLSurfaceView trông giống như:


public class GLPreview extends GLSurfaceView 
{ 
    private static final String TAG = "GLPreview"; 

    public GLPreview(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 
     // this.setZOrderMediaOverlay(true);   
    } 

    public void onPause() 
    { 
     super.onPause(); 
     Log.d(TAG, "GLPreview: OnPause"); 
    } 

    public void onResume() 
    { 
     // this.setZOrderMediaOverlay(true);   
     super.onResume(); 
     Log.d(TAG, "GLPreview: OnResume"); 
    } 

    public void surfaceCreated(SurfaceHolder holder) 
    { 
     Log.d(TAG, "GLPreview: surfaceCreated"); 
     super.surfaceCreated(holder); 
    } 

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) 
    { 
     Log.d(TAG, String.format("GLPreview: surfaceChanged, format=%d, w=%d, h=%d", format, w, h)); 
     super.surfaceChanged(holder, format, w, h); 
    } 

    public void surfaceDestroyed(SurfaceHolder holder) 
    { 
     Log.d(TAG, "GLPreview: surfaceDestroyed"); 
     super.surfaceDestroyed(holder); 
    } 

    protected void onAttachedToWindow() 
    { 
     Log.d(TAG, "GLPreview: onAttachedToWindow"); 
     super.onAttachedToWindow(); 
    } 

    protected void onDetachedFromWindow() 
    { 
     Log.d(TAG, "GLPreview: onDetachedFromWindow"); 
     super.onDetachedFromWindow(); 
    } 

    protected void onWindowVisibilityChanged (int vis) 
    { 
     String newVisibility; 
     switch (vis) 
     { 
      case View.GONE: 
       newVisibility = "GONE"; 
       break; 
      case View.INVISIBLE: 
       newVisibility = "INVISIBLE"; 
       break; 
      case View.VISIBLE: 
       newVisibility = "VISIBLE"; 
       break; 
      default: 
       newVisibility = String.format("Unknown constant %d", vis); 
     } 

     Log.d(TAG, String.format("GLPreview: onWindowVisibilityChanged -> %s", newVisibility)); 
     super.onWindowVisibilityChanged(vis); 
    } 
} 
 

Đây là chuỗi các sự kiện khi tôi khởi động ứng dụng:

 
GLPreview: OnResume 
GLPreview: onAttachedToWindow 
GLPreview: onWindowVisibilityChanged -> VISIBLE 
GLPreview: surfaceCreated 
GLPreview: surfaceChanged, format=1, w=800, h=480 

Vì vậy, tôi cho rằng setZOrderMediaOverlay() cần phải được gọi là trong cả hai onResume() hoặc trong constructor. Tuy nhiên, tôi đã thử các kết hợp khác nhau của setZOrderMediaOverlay() với true hoặc false, trong các lớp GLSurfaceView hoặc SurfaceView, nhưng không có kết quả nào giúp khắc phục sự cố.

Tôi khá mới khi nói đến lập trình Android. Tôi đã đi quá xa nhưng vào thời điểm này tôi cần sự giúp đỡ. Nếu ai đó đã sử dụng setZOrderMediaOverlay() thành công trong trường hợp này và đã làm việc với onResume() hãy cho tôi biết cách thực hiện điều này.

Cảm ơn rất nhiều trước!

+1

FWIW, xem http://stackoverflow.com/questions/5648221/fighting-with-surfaceview-camera-and-opengl/25020225#25020225 đối với một số ghi chú về chồng chéo SurfaceViews. – fadden

Trả lời

14

Tôi đã gặp khó khăn với cùng một vấn đề trong một thời gian, nhưng hãy tin rằng mã bên dưới hiện hoạt động. (Nó tiếp tục hoạt động sau khi tạm dừng/khóa bất kể máy ảnh đang bật hay tắt).

Thứ nhất, tôi chưa có bất kỳ chế độ xem nào được xác định trong tệp bố cục - chúng được tạo trong mã. Sau đây được gọi từ phương thức onCreate() chính - Lưu ý setZOrderMediaOverlay() trên augScreen.

Tôi đã không làm gì đặc biệt trong onPause() hoặc onResume() ngoài việc truyền trên (Tạm dừng) và onResume() đến augScreen.

 // 1 - Camera Preview 
     camScreen = new CameraPreview(this); 
     setContentView(camScreen, new LayoutParams(
       LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); 

    // 2 - 3D object display 
     augScreen = new AR_SurfaceView(this, getViewRange()); 
     addContentView(augScreen, new LayoutParams(
       LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 
     augScreen.setZOrderMediaOverlay(true); 

    // 3 - Permanent overlay 
    RelativeLayout overlayScreen = new OverlayView(this); 
    addContentView(overlayScreen, new LayoutParams(
      LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); 
    overlayScreen.setVisibility(View.VISIBLE); 

    // 4 - UI buttons (toggleable) 
     uiScreen = new UserInterfaceView(this); 
     addContentView(uiScreen, new LayoutParams(
       LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); 
+1

Cảm ơn, gọi 'setZOrderMediaOverlay()' trong 'onCreate()' đã giải quyết vấn đề này. BTW, tôi vẫn có tệp bố cục XML; Tôi không chuyển đổi ứng dụng để tạo chế độ xem trong mã. Tôi biết tôi đã không đề cập đến điều này trong câu hỏi nhưng cùng một ứng dụng có một số mã được sử dụng để vẽ trên bề mặt xem trước máy ảnh (DrawText đơn giản cho thấy khung hình/giây). Bây giờ tôi phải tìm ra lý do tại sao mã này ngừng hoạt động sau khi tôi thực hiện thay đổi 'setZOrderMediaOverlay()'. – alokoko

+0

Bởi "không hoạt động", tôi có nghĩa là mã đang được gọi, tôi thấy xem trước máy ảnh và các đối tượng 3D, nhưng văn bản fps không được vẽ trên bề mặt xem trước máy ảnh nữa. Hmmmmmm. – alokoko

0

Câu trả lời của Awila_Tech cũng giúp tôi.Tôi đã sử dụng một GLSurfaceView và gọn gàng gọi là onPause và onResume của nó trong onPause của hoạt động và onResume, nhưng 1 trong số 5 lần màn hình của tôi vẫn còn màu đen trong khi onDrawFrame thực tế đang được gọi.

Để tóm tắt:

public class OpenGLApp extends Activity implements GLSurfaceView.Renderer { 
    private GLSurfaceView mGLSurfaceView; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     mGLSurfaceView = new GLSurfaceView(this); 
     mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 8); 
     mGLSurfaceView.setRenderer(this); 
     mGLSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT); 
     mGLSurfaceView.setKeepScreenOn(true); 
     mGLSurfaceView.setDrawingCacheEnabled(true); 
     mGLSurfaceView.setZOrderOnTop(true); 

     setContentView(mGLSurfaceView); 
     //... 
    } 

    @Override 
    protected void onPause() { 
     //... 
     mGLSurfaceView.onPause(); 
     super.onPause(); 
    } 

    @Override 
    protected void onResume() { 
     mGLSurfaceView.onResume(); 
     //... 
     super.onResume(); 
    } 
} 
+0

Pete, Bạn không được phép gọi super.onPause() và super.onResume() trước mGLSurfaceView? –

Các vấn đề liên quan