如何在XML布局中使用扩展类?

2 android surfaceview android-layout android-camera

我为相机预览创建了一个扩展的SurfaceView类.

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    SurfaceHolder mHolder;
    Camera mCamera;

    CameraPreview(Context context) {
        super(context);

        mHolder = this.getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, acquire the camera and tell it where
        // to draw.
        try {
            mCamera = Camera.open();
            mCamera.setPreviewDisplay(holder);
        } catch (Exception e){
            Log.wtf("surfaceCreated", e.toString());
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        try {
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        } catch (Exception e){
            Log.wtf("surfaceDestroyed", e.toString());
        }
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        try {
            Camera.Parameters parameters = mCamera.getParameters();
            // parameters.setPreviewSize(w, h);
            // parameters.setPreviewSize(222, 222);
            mCamera.setParameters(parameters);
            mCamera.startPreview();
        } catch (Exception e){
            Log.wtf("surfaceChanged", e.toString());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在以下活动中使用时,它可以作为全屏预览:

public class CameraActivity extends Activity {
    CameraPreview mPreview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE); 
        mPreview = new CameraPreview(this);
        setContentView(mPreview);
    }
}
Run Code Online (Sandbox Code Playgroud)

当我尝试在XML布局文件中使用它时,它会产生ClassNotFoundException.

<CameraPreview class="com.xxxxxx.camera3.CameraPreview"
    android:layout_width="260dp"
    android:layout_height="260dp"
    android:id="@+id/surfaceView"
    android:background="#ff404040"
    android:layout_gravity="center_horizontal"/> 
Run Code Online (Sandbox Code Playgroud)

我需要做些什么来使它工作?如何在SurfaceView中放置相机预览?

Luc*_*ord 5

假设您的包含新视图的包名为:com.ranandar.views

在您的xml中执行以下操作:

<com.ranandar.views.CameraPreview
    android:layout_width="260dp"
    android:layout_height="260dp"
    android:id="@+id/surfaceView"
    android:background="#ff404040"
    android:layout_gravity="center_horizontal"/> 
Run Code Online (Sandbox Code Playgroud)

这在com.ranandar.views包中查找,找到定义该视图的类,并使用它.

但是在您的活动中存在问题.您正在将内容视图设置为该表面视图,这是不对的.

编辑:添加您请求的示例.

public class CameraPreview extends SurfaceView implements   SurfaceHolder.Callback {
    SurfaceHolder mHolder;
    Camera mCamera;

    CameraPreview(Context context) {
        super(context);
        init();
    }

    CameraPreview(Context context, AttributeSet attrs){
        super(context, attrs);
        init();
    }

    public void init(){
        mHolder = this.getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    //additionally with all your other code
    ...
}
Run Code Online (Sandbox Code Playgroud)

所以我所做的就是添加定义自定义视图所需的构造函数,并在XML中使用它.您需要定义其他构造函数,以便在XML中使用它时,属性集将传递给视图.属性集是您声明的各种字段,如layout_width/height,background等.否则,如果没有此构造函数,CameraPreview将无法通过传递没有构造函数的属性集来处理它.双参数构造函数super(context,attrs)中的调用使用您定义的属性进行处理.

您可能需要进一步学习的文档:创建自定义视图

需要将您的XML文件的根视图设置为ViewGroup类,如RelativeLayout,LinearLayout等...在这种情况下执行框架布局:

 <?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root"
    android:layout_width="match_parent"
    andorid:layout_height="match_parent">

    <com.ranandar.views.CameraPreview
        android:id="@+id/camera_preview"
        android:layout_width="260dp"
        android:layout_height="260dp"
        android:id="@+id/surfaceView"
        android:background="#ff404040"
        android:layout_gravity="center_horizontal"/> 

</FrameLayout>
Run Code Online (Sandbox Code Playgroud)

假设这个xml文件名为activity_main.xml

请执行下列操作:

public class CameraActivity extends Activity {
    CameraPreview mPreview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        requestWindowFeature(Window.FEATURE_NO_TITLE); 
        mPreview = (CameraPreview) findViewById(R.id.camera_preview);
    }
}
Run Code Online (Sandbox Code Playgroud)

始终确保首先设置setContentView,然后再调整可能调用布局组件的其他内容.这对你来说可能是一个问题