You need to have certain constructors to be able to instantiate your custom view through XML.
http://developer.android.com/training/custom-views/create-view.html#subclassview
I don't want to provide a working solution though.
Question
I'm attempting to create a custom SurfaceView that will be used draw a menu/or other components on top of another SurfaceView that is currently display the Camera’s live output.
Therefore I created a Class “OverlayOfSurfaceView” that extends SurfaceView , see below:
package com.net.app.barcode;
import com.net.app.R;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class OverlayOfSurfaceView extends SurfaceView implements
SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Context context;
private LinearLayout linearMenu = null;
public OverlayOfSurfaceView(Context context, AttributeSet attr) {
super(context,attr);
this.context = context;
// TODO Auto-generated constructor stub
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
linearMenu = (LinearLayout) this.findViewById(R.layout.barcode_scanner_overlay_menu);
setFocusable(true);
requestFocus();
}
@Override
public void onDraw(Canvas canvas) {
drawGuidance(canvas);
}
public void drawGuidance(Canvas canvas) {
Log.w(this.getClass().getName(),"drawGuidance(Canvas canvas)");
Paint paintRed = new Paint();
paintRed.setStyle(Paint.Style.STROKE);
paintRed.setStrokeWidth(6f);
paintRed.setAntiAlias(true);
paintRed.setColor(Color.BLUE);
// drawMiddleline
canvas.drawLine( this.getHeight()/2,0,this.getWidth(),this.getHeight()/2 , paintRed);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.w(this.getClass().getName(),"surface created");
// TODO Auto-generated method stub
setWillNotDraw(false);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
Log.w(this.getClass().getName(),"surface changed");
// TODO Auto-generated method stub
// If your preview can change or rotate, take care of those events
// here.
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.w(this.getClass().getName(),"surface destroyed");
// TODO Auto-generated method stub
// empty. Take care of releasing resources here
}
}//end class
The layout of OverlayOfSurfaceView, see below:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/LayoutForPreview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:screenOrientation="portrait"
android:scaleType="fitXY" >
<SurfaceView
android:id="@+id/surfaceViewBarcodeScanner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY"
/>
<com.yourmarketnet.yourmarketapp.barcode.OverlayOfSurfaceView
android:id="@+id/overlay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY" />
</FrameLayout>
Finally below is the relevant snippet of onCreate() method, in the Activity () were im instantiating the custom SurfaceView called OverlayOfSurfaceView:
public class ScanVinFromBarcodeActivity extends Activity {
//irrelevant parts not included in this post
// onCreate method, instantiates layouts & surfaceView used for video preview
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_barcode_vin_scanner);
Log.d("ClassScanViewBarcodeActivity", "onCreate ");
// create surfaceView for previewing of camera image
FrameLayoutBarcodeScanner = (FrameLayout) findViewById(R.id.LayoutForPreview);
surfaceViewBarcodeScanner = (SurfaceView) findViewById(R.id.surfaceViewBarcodeScanner);
surfaceViewLayOver = (OverlayOfSurfaceView) findViewById(R.id.overlay);
//make the background transparent so the user can see surfaceViewBarcodeScanner behind this SurfaceView
surfaceViewLayOver.setAlpha(0);
//pass overlay to layout
FrameLayoutBarcodeScanner.addView(surfaceViewLayOver);
globalContext = this.getApplicationContext();
initializeGlobalCamera();
//removed code irrelevant to this post
}//end onCreate
//irrelevant parts not included in this post
}//end Activity class
Actual error snippets from logs:
Finally below is the relevant snippet of onCreate() method, in the Activity where I am instantiating the Class: Here is the runtime exception that causes the nasty crash:
04-04 18:05:40.833: E/AndroidRuntime(15123): java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.net.app/com.net.app.barcode.ScanVinFromBarcodeActivity}:
android.view.InflateException: Binary XML file line #18:
Error inflating class com.net.app.barcode.OverlayOfSurfaceView
04-04 18:05:40.833: E/AndroidRuntime(15123): Caused by: android.view.InflateException:
Binary XML file line #18: Error inflating class com.net.app.barcode.OverlayOfSurfaceView
04-04 18:05:40.833: E/AndroidRuntime(15123):
Caused by: java.lang.NoSuchMethodException: <init>
[class android.content.Context, interface android.util.AttributeSet]
Please be kind enough to provide working solutions to this problem. Thanks
La solution
You need to have certain constructors to be able to instantiate your custom view through XML.
http://developer.android.com/training/custom-views/create-view.html#subclassview
I don't want to provide a working solution though.