2013-05-10 52 views
2

我一直在嘗試創建一個Camera Preview,它在預覽中顯示帶有多個透明圖像的View Pager。但是,我得到這個錯誤:在CameraPreview上使用ViewPager

05-10 03:31:23.614: E/AndroidRuntime(674): FATAL EXCEPTION: main 
05-10 03:31:23.614: E/AndroidRuntime(674): java.lang.NullPointerException 
05-10 03:31:23.614: E/AndroidRuntime(674): at com.android.gs1.MainActivity$CameraPreview.surfaceCreated(MainActivity.java:102) 
05-10 03:31:23.614: E/AndroidRuntime(674): at android.view.SurfaceView.updateWindow(SurfaceView.java:562) 
05-10 03:31:23.614: E/AndroidRuntime(674): at android.view.SurfaceView.access$000(SurfaceView.java:82) 
05-10 03:31:23.614: E/AndroidRuntime(674): at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:171) 
05-10 03:31:23.614: E/AndroidRuntime(674): at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:590) 
05-10 03:31:23.614: E/AndroidRuntime(674): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1596) 
05-10 03:31:23.614: E/AndroidRuntime(674): at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2418) 
05-10 03:31:23.614: E/AndroidRuntime(674): at android.os.Handler.dispatchMessage(Handler.java:99) 
05-10 03:31:23.614: E/AndroidRuntime(674): at android.os.Looper.loop(Looper.java:137) 
05-10 03:31:23.614: E/AndroidRuntime(674): at android.app.ActivityThread.main(ActivityThread.java:4340) 
05-10 03:31:23.614: E/AndroidRuntime(674): at java.lang.reflect.Method.invokeNative(Native Method) 
05-10 03:31:23.614: E/AndroidRuntime(674): at java.lang.reflect.Method.invoke(Method.java:511) 
05-10 03:31:23.614: E/AndroidRuntime(674): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 
05-10 03:31:23.614: E/AndroidRuntime(674): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 
05-10 03:31:23.614: E/AndroidRuntime(674): at dalvik.system.NativeStart.main(Native Method) 

這裏是我的代碼:

package com.android.gs1; 

import java.io.IOException; 
import android.os.Bundle; 
import android.os.Parcelable; 
import android.app.Activity; 
import android.content.Context; 
import android.hardware.Camera; 
import android.support.v4.view.PagerAdapter; 
import android.support.v4.view.ViewPager; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.LinearLayout; 
import android.widget.Toast; 


public class MainActivity extends Activity { 

ViewPager vp; 
Camera mCamera; 
SurfaceHolder mHolder; 
static int j; 
private vpAdapter myAdapter; 
CameraPreview preview; 

public static void passPageNumber(int i){ 
    j = i; 
} 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 


    Toast.makeText(getApplicationContext(), "Swipe Left or Right to Select an Option", Toast.LENGTH_LONG).show(); 
    vp = (ViewPager) findViewById(R.id.viewpager); 
    myAdapter = new vpAdapter(); 
    preview = new CameraPreview(getApplicationContext(), mCamera); 
    ((LinearLayout) findViewById(R.id.preview)).addView(preview); 
    vp.setAdapter(myAdapter); 
} 

private class CameraPreview extends SurfaceView implements SurfaceHolder.Callback{ 


    private final String TAG = null; 


    public CameraPreview(Context context, Camera camera) { 
     super(context); 
     // TODO Auto-generated constructor stub 
     mCamera = camera; 

     // Install a SurfaceHolder.Callback so we get notified when the 
     // underlying surface is created and destroyed. 
     mHolder = getHolder(); 
     mHolder.addCallback(this); 

     // deprecated setting, but required on Android versions prior to 3.0 
     // mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    } 

    @Override 
    public void surfaceChanged(SurfaceHolder holder, int format, int width, 
      int height) { 
     // TODO Auto-generated method stub 
     if (mHolder.getSurface() == null){ 
       // preview surface does not exist 
       return; 
      } 

      // stop preview before making changes 
      try { 
       mCamera.stopPreview(); 
      } catch (Exception e){ 
       // ignore: tried to stop a non-existent preview 
      } 

      // set preview size and make any resize, rotate or 
      // reformatting changes here 

      // start preview with new settings 
      try { 
       mCamera.setPreviewDisplay(mHolder); 
       mCamera.startPreview(); 

      } catch (Exception e){ 
       Log.d(TAG, "Error starting camera preview: " + e.getMessage()); 
      } 
    } 

    @Override 
    public void surfaceCreated(SurfaceHolder holder) { 
     // TODO Auto-generated method stub 
     try { 
      mCamera = Camera.open(); 
      mCamera.setPreviewDisplay(holder); 
      mCamera.startPreview(); 
     } catch (IOException e) { 
      Log.d(TAG, "Error setting camera preview: " + e.getMessage()); 
     } 
    } 

    @Override 
    public void surfaceDestroyed(SurfaceHolder holder) { 
     // TODO Auto-generated method stub 

    } 

} 
private class vpAdapter extends PagerAdapter{ 

    @Override 
    public int getCount() { 
     // TODO Auto-generated method stub 
     return 5; 
    } 

    @Override 
    public boolean isViewFromObject(View view, Object object) { 
     // TODO Auto-generated method stub 
     return view == ((LinearLayout)object); 
    } 

    @Override 
    public void destroyItem(ViewGroup container, int position, Object object) { 
     // TODO Auto-generated method stub 
     ((ViewPager)container).removeView((LinearLayout)object); 
    } 

    @Override 
    public void finishUpdate(ViewGroup container) { 
     // TODO Auto-generated method stub 

    } 


    @Override 
    public Object instantiateItem(View container, int position) { 
     // TODO Auto-generated method stub 
     LayoutInflater inflater = (LayoutInflater)container.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     View v = null; 

     switch(position){ 
     case 0: 
      v = inflater.inflate(R.layout.first, null); 
      break; 
     case 1: 
      v = inflater.inflate(R.layout.second, null); 
      break; 
     case 2: 
      v = inflater.inflate(R.layout.third, null); 
      break; 
     case 3: 
      v = inflater.inflate(R.layout.fourth, null); 
      break; 
     case 4: 
      v = inflater.inflate(R.layout.fifth, null); 
      break; 
     } 


     ((ViewPager)container).addView(v, 0); 
     return v; 
    } 
    @Override 
    public void startUpdate(ViewGroup container) { 
     // TODO Auto-generated method stub 

    } 
    @Override 
    public Parcelable saveState() { 
     // TODO Auto-generated method stub 
     return null; 
    } 

} 
} 

這裏是我的xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:tools="http://schemas.android.com/tools" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
tools:context=".MainActivity" 
android:background="#545454" > 

<android.support.v4.view.ViewPager 
    android:id="@+android:id/viewpager" 
    android:layout_width="0dip" 
    android:layout_height="wrap_content" 
    android:layout_weight="0.49" /> 
<LinearLayout 
    android:id="@+id/preview" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content"> 
</LinearLayout> 
</LinearLayout> 

有對viewpager五個XML。他們都是這樣的,但有不同的名字和ID。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
android:orientation="vertical" 
> 

<ImageView 
android:id="@+id/image1" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:adjustViewBounds="false" 
android:contentDescription="@string/description_image_1" 
android:scaleType="fitXY" 
android:src="@drawable/first" /> 

</LinearLayout> 

非常感謝您

編輯:有人問我我的代碼的最後工作版本。這裏是:

public class MainActivity extends Activity { 

ViewPager vp; 
vpAdapter myAdapter; 
Camera camera = null; 
SurfaceHolder previewHolder = null; 
private SurfaceView preview = null; 
private boolean inPreview = false; 
private boolean cameraConfigured = false; 
public static String[] arrayURL; 
public static boolean urlsPassed; 
private View mContentView; 
private View mLoadingView; 

private int mShortAnimationDuration; 


@SuppressWarnings("deprecation") 
@SuppressLint("NewApi") 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    requestWindowFeature(Window.FEATURE_NO_TITLE); 
    setContentView(R.layout.activity_main); 
    Toast.makeText(getApplicationContext(), "Swipe Left or Right to Select an Option", Toast.LENGTH_SHORT).show(); 
    //NEW CODE 

    mContentView = findViewById(R.id.content); 
    mLoadingView = findViewById(R.id.loading_spinner); 
    mContentView.setVisibility(View.GONE); 
    mShortAnimationDuration = getResources().getInteger(
      android.R.integer.config_shortAnimTime); 
    //NEW CODE 
    preview=(SurfaceView)findViewById(R.id.preview); 
    preview.setZOrderOnTop(false); 
    previewHolder=preview.getHolder(); 
    previewHolder.addCallback(surfaceCallback); 
    previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 

} 
private void crossfade() { 

    // Set the content view to 0% opacity but visible, so that it is visible 
    // (but fully transparent) during the animation. 
    mContentView.setAlpha(0f); 
    mContentView.setVisibility(View.VISIBLE); 

    // Animate the content view to 100% opacity, and clear any animation 
    // listener set on the view. 
    mContentView.animate() 
      .alpha(1f) 
      .setDuration(mShortAnimationDuration) 
      .setListener(null); 

    // Animate the loading view to 0% opacity. After the animation ends, 
    // set its visibility to GONE as an optimization step (it won't 
    // participate in layout passes, etc.) 
    mLoadingView.animate() 
      .alpha(0f) 
      .setDuration(mShortAnimationDuration) 
      .setListener(new AnimatorListenerAdapter() { 
       @Override 
       public void onAnimationEnd(Animator animation) { 
        mLoadingView.setVisibility(View.GONE); 
       } 
      }); 
} 
    public static void assignURL(String[] urls){ 
    arrayURL = urls; 
} 

    public static void urlsPassed(boolean transfer){ 
     urlsPassed = transfer; 
    } 

@Override 
    public void onResume() { 
    super.onResume(); 
    camera=Camera.open(); 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    getMenuInflater().inflate(R.menu.main, menu); 
    return true; 
} 
@Override 
    public void onPause() { 
    if (inPreview) { 
     camera.stopPreview(); 
    } 

    camera.release(); 
    camera=null; 
    inPreview=false; 

    super.onPause(); 
    } 

private Camera.Size getBestPreviewSize(int width, int height,Camera.Parameters parameters) { 

    Camera.Size result=null; 
    for (Camera.Size size : parameters.getSupportedPreviewSizes()) { 
     if (size.width<=width && size.height<=height) { 
      if (result==null) { 
       result=size; 
      } 
      else { 
       int resultArea=result.width*result.height; 
       int newArea=size.width*size.height; 

       if (newArea>resultArea) { 
        result=size; 
       } 
      } 
     } 
    } 

    return(result); 
} 
private void initPreview(int width, int height) { 
    if (camera!=null && previewHolder.getSurface()!=null) { 
     try { 
     camera.setPreviewDisplay(previewHolder); 
     } 
     catch (Throwable t) { 
     Log.e("PreviewDemo-surfaceCallback", 
       "Exception in setPreviewDisplay()", t); 
     Toast 
      .makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_LONG) 
      .show(); 
     } 

     if (!cameraConfigured) { 
     Camera.Parameters parameters=camera.getParameters(); 
     Camera.Size size=getBestPreviewSize(width, height, 
              parameters); 

     if (size!=null) { 
      parameters.setPreviewSize(size.width, size.height); 
      camera.setParameters(parameters); 
      cameraConfigured=true; 
     } 
     } 
    } 
    } 

private void startPreview() { 
     if (cameraConfigured && camera!=null) { 
      camera.startPreview(); 
      inPreview=true; 
      crossfade(); 
      if(urlsPassed){ 
      myAdapter = new vpAdapter(this, arrayURL); 
      vp = (ViewPager) findViewById(R.id.viewpager); 
      vp.setAdapter(myAdapter); 
      vp.setCurrentItem(0); 
      } 
     } 
     } 

SurfaceHolder.Callback surfaceCallback=new SurfaceHolder.Callback() { 
     @Override 
     public void surfaceCreated(SurfaceHolder holder) { 
      // no-op -- wait until surfaceChanged() 
     } 

     @Override 
     public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) { 


      Camera.Parameters parameters = camera.getParameters(); 
      parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); 
      camera.setParameters(parameters); 
      initPreview(width, height); 
      startPreview(); 
      camera.autoFocus(null); 
     } 

     @Override 
     public void surfaceDestroyed(SurfaceHolder holder) { 
      // no-op 
     } 
     }; 

} 
+0

你確定你的尋呼機視圖的id是正確的android:id = @ + android:id/viewpager?看起來好像是 – Evos 2013-05-10 05:18:33

+0

ViewPager完美地由它自己完成。我只是想在它下面的佈局中顯示一個CameraPreview。 – 2013-05-10 13:49:15

回答

1

對於未來的人們正在努力解決這類問題。我找到了解決方案:

首先,無論您在預覽頂部設置了什麼,都必須放置在佈局中的SurfaceView之後。例如:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    tools:context=".MainActivity" 
    android:background="#ffff"> 

    <android.view.SurfaceView 
     android:id="@+id/preview" 
     android:layout_width="4978dp" 
     android:layout_height="5131dp"> 
    </android.view.SurfaceView> 

    <android.support.v4.view.ViewPager 
     android:id="@+android:id/viewpager" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent"/> 
</RelativeLayout> 

其次,在Java文件中,SurfaceView必須將setZOrderOnTop設置爲false。例如:

​​

三,設置佈局,這將是對CameraPreview頂部調用相機功能startPreview後。

就是這樣。

+1

這是極有幫助的。謝謝 !!! :) – 2014-04-03 20:19:59

+1

非常好!我很高興它幫助:) – 2014-04-04 00:04:27