我很感激当前这个问题的一些帮助。我想我理解问题的原因,但我不知道如何解决它。我有两个自定义视图,一个实现ViewGroup,另一个实现View。
CameraSourcePreview和GraphicOverlay
然而,它们都是T的通用,其中T:GraphicOverlay< \ T> .Graphic
在BarcodeFragmentActivity中。第64行。 的setContentView(Resource.Layout.Barcode_Capture)
引发以下错误。
System.NotSupportedException:不支持从Java构造泛型类型的实例,因为无法确定类型参数。发生
我不确定如何创建完整的堆栈跟踪,因为我使用手机作为测试设备。程序不会在模拟器上运行。
Github上的代码:https://github.com/StormMaster12/StockApp。 认为在那里看到它比在我的所有代码中复制更容易。
编辑代码投掷错误。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Content.PM;
using Android.Gms.Vision.Barcodes;
using Android.Gms.Common.Apis;
using Android.Gms.Common;
using Android.Gms.Vision;
using Android.Hardware;
using Android.Support.V4.View;
using Android.Support.V4.App;
using Android.Support.V7.App;
using Android.Support.Design.Widget;
using StockApp.UI;
using Android.Util;
namespace StockApp.BarcodeReader
{
[Activity(Label = "Barcode Fragment Activity")]
class BarcodeFragmentActivity : AppCompatActivity
{
private static string tag = "Barcode-Reader";
private static int RC_HANDLE_GMS = 9001;
private static int RC_HANDLE_CAMERA_PERM = 2;
public static string AutoFocus = "AutoFocus";
public static string UseFlash = "UseFlash";
public static string BarcodeObject = "Barcode";
private CameraSourcePreview<BarcodeGraphic> mPreview;
private Android.Gms.Vision.CameraSource mCameraSource;
private GraphicOverlay<BarcodeGraphic> mGraphicOverlay;
private ScaleGestureDetector scaleGestureDetector;
private GestureDetector getsureDetector;
private View layout;
private static BarcodeFragmentActivity thisInstance;
public override View OnCreateView(View parent, string name, Context context, IAttributeSet attrs)
{
return base.OnCreateView(parent, name, context, attrs);
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
thisInstance = this;
SetContentView(Resource.Layout.Barcode_Capture);
//LayoutInflater inflater = LayoutInflater.From(this);
//ViewGroup viewGroup = (ViewGroup)FindViewById(Resource.Id.preview);
//View child = inflater.Inflate(Resource.Layout.layout1, viewGroup, true);
mPreview = (CameraSourcePreview<BarcodeGraphic>)FindViewById(Resource.Id.preview);
mGraphicOverlay = (GraphicOverlay<BarcodeGraphic>)FindViewById(Resource.Id.graphicOverlay);
bool autoFocus = Intent.GetBooleanExtra(AutoFocus, false);
bool useFlash = Intent.GetBooleanExtra(UseFlash, false);
int rc = (int) ActivityCompat.CheckSelfPermission(this, Manifest.Permission.Camera);
if (rc == (int) Permission.Granted)
{
createCameraSource(autoFocus, useFlash);
}
else
{
requestCameraPermission();
}
getsureDetector = new GestureDetector(this, new CaptureGestureListener());
}
private void requestCameraPermission()
{
string[] permissions = new string[] { Manifest.Permission.CallPhone };
if (ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.Camera))
{
Snackbar.Make(layout, "Require Camera Permions To Read Barcodes", Snackbar.LengthIndefinite)
.SetAction("Ok", new Action<View> (delegate(View obj)
{
ActivityCompat.RequestPermissions(this, permissions, RC_HANDLE_CAMERA_PERM);
}
)).Show();
}
else
{
ActivityCompat.RequestPermissions(this, permissions, RC_HANDLE_CAMERA_PERM);
}
//Activity thisActivity = this;
//View.IOnClickListener listener = new View.IOnClickListener;
}
public override bool OnTouchEvent(MotionEvent e)
{
bool b = scaleGestureDetector.OnTouchEvent(e);
bool c = getsureDetector.OnTouchEvent(e);
return b || c || base.OnTouchEvent(e);
}
private void createCameraSource(bool autoFocus, bool useFlash)
{
Context context = ApplicationContext;
BarcodeDetector barcodeDetector = new BarcodeDetector.Builder(context).Build();
BarcodeTrackerFactory barcodeFactory = new BarcodeTrackerFactory(mGraphicOverlay);
barcodeDetector.SetProcessor(
new MultiProcessor.Builder(barcodeFactory).Build());
if (!barcodeDetector.IsOperational)
{
IntentFilter lowstorageFilter = new IntentFilter(Intent.ActionDeviceStorageLow);
bool hasLowStorage = RegisterReceiver(null, lowstorageFilter) != null;
if (hasLowStorage)
{
Toast.MakeText(this, "Low Storage Error", ToastLength.Long);
}
}
Android.Gms.Vision.CameraSource.Builder builder = new Android.Gms.Vision.CameraSource.Builder(base.ApplicationContext, barcodeDetector)
.SetFacing(Android.Gms.Vision.CameraFacing.Back)
.SetRequestedPreviewSize(1600, 1024)
.SetRequestedFps(15.0f)
.SetAutoFocusEnabled(true);
mCameraSource = builder.Build();
}
private void startCameraSource()
{
int code = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(ApplicationContext);
if(code != ConnectionResult.Success)
{
Dialog dig = GoogleApiAvailability.Instance.GetErrorDialog(this, code, RC_HANDLE_GMS);
dig.Show();
}
if (mCameraSource != null)
{
try
{
mPreview.start(mCameraSource, mGraphicOverlay);
}
catch (InvalidOperationException)
{
mCameraSource.Release();
mCameraSource = null;
}
}
}
private bool OnTap(float rawX, float rawY)
{
int[] location = new int[2];
mGraphicOverlay.GetLocationOnScreen(location);
float x = (rawX - location[0]);
float y = (rawY - location[1]);
Barcode best = null;
float bestDistance = float.MaxValue;
foreach (BarcodeGraphic graphic in mGraphicOverlay.getGraphics())
{
Barcode barcode = graphic.GetBarcode();
if(barcode.BoundingBox.Contains((int)x,(int)y))
{
best = barcode;
break;
}
float dx = x - barcode.BoundingBox.CenterX();
float dy = y - barcode.BoundingBox.CenterY();
float distance = (dx * dx) + (dy * dy);
if ( distance > bestDistance)
{
best = barcode;
bestDistance = distance;
}
if (best != null)
{
Intent data = new Intent();
data.PutExtra(BarcodeObject, best);
SetResult(CommonStatusCodes.Success, data);
Finish();
return true;
}
}
return false;
}
protected override void OnResume()
{
base.OnResume();
startCameraSource();
}
protected override void OnPause()
{
base.OnPause();
if (mPreview != null)
{
mPreview.stop();
}
}
protected override void OnDestroy()
{
base.OnDestroy();
if(mPreview != null)
{
mPreview.release();
}
}
private class CaptureGestureListener : GestureDetector.SimpleOnGestureListener
{
public override bool OnSingleTapConfirmed(MotionEvent e)
{
return thisInstance.OnTap(e.RawX, e.RawY) || base.OnSingleTapConfirmed(e);
}
}
private class ScaleListener : ScaleGestureDetector.IOnScaleGestureListener
{
public IntPtr Handle => throw new NotImplementedException();
public void Dispose()
{
throw new NotImplementedException();
}
public bool OnScale(ScaleGestureDetector detector)
{
return false;
}
public bool OnScaleBegin(ScaleGestureDetector detector)
{
return true;
}
public void OnScaleEnd(ScaleGestureDetector detector)
{
}
}
}
}
正在调用的代码。
CameraSourcePreview
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Gms.Vision;
using Android.Util;
using Android.Support.Annotation;
using Android.Gms.Common.Images;
using Android.Content.Res;
using Android.Graphics;
namespace StockApp.UI
{
[Register("stockapp.stockapp.ui.CameraSourcePreview")]
class CameraSourcePreview<T> : ViewGroup where T : GraphicOverlay<T>.Graphic
{
private static string TAG = "CameraSourcePreview";
private Context mContext;
private SurfaceView mSurfaceView;
public bool mStartRequested;
private bool mSurfaceAvaialbe;
private Android.Gms.Vision.CameraSource mCameraSource;
private GraphicOverlay<T> mOverlay;
private static CameraSourcePreview<T> Instance { get; set; }
public CameraSourcePreview(Context context, IAttributeSet attrs) : base(context,attrs)
{
mContext = context;
mStartRequested = false;
mSurfaceAvaialbe = false;
SurfaceCallback instance = new SurfaceCallback();
mSurfaceView = new SurfaceView(context);
mSurfaceView.Holder.AddCallback(instance);
AddView(mSurfaceView);
}
public void start(Android.Gms.Vision.CameraSource cameraSource)
{
if (cameraSource == null)
{
stop();
}
mCameraSource = cameraSource;
if(mCameraSource != null)
{
mStartRequested = true;
startIfReady();
}
}
public void start(Android.Gms.Vision.CameraSource cameraSource, GraphicOverlay<T> graphicOverlay)
{
mOverlay = graphicOverlay;
start(cameraSource);
}
public void stop()
{
if(mCameraSource != null)
{
mCameraSource.Stop();
}
}
public void release()
{
if(mCameraSource != null)
{
mCameraSource.Release();
mCameraSource = null;
}
}
private bool isPortaitMode()
{
int orientation = (int)mContext.Resources.Configuration.Orientation;
if (orientation == (int)Android.Content.Res.Orientation.Landscape)
{
return false;
}
else if (orientation == (int)Android.Content.Res.Orientation.Portrait)
{
return true;
}
return false;
}
private void startIfReady()
{
if (mStartRequested && mSurfaceAvaialbe)
{
mCameraSource.Start(mSurfaceView.Holder);
if (mOverlay != null)
{
Android.Gms.Common.Images.Size size = mCameraSource.PreviewSize;
int min = Math.Min(size.Width, size.Height);
int max = Math.Max(size.Width, size.Width);
if(isPortaitMode())
{
mOverlay.setCameraInfo(min, max, (int)mCameraSource.CameraFacing);
}
else
{
mOverlay.setCameraInfo(max, min, (int)mCameraSource.CameraFacing);
}
mOverlay.Clear();
}
mStartRequested = false;
}
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
int intWidth = 320;
int intHeight = 240;
if(mCameraSource != null)
{
Android.Gms.Common.Images.Size size = mCameraSource.PreviewSize;
if(size != null)
{
intWidth = size.Width;
intHeight = size.Height;
}
}
if(isPortaitMode())
{
int tmp = intWidth;
intHeight = intWidth;
intWidth = tmp;
}
int layoutWidth = l - r;
int layoutHeight = t - b;
int childWidth = layoutWidth;
int childHeight = (int)(((float)layoutWidth / (float) intHeight)*intWidth);
if (childHeight > layoutWidth)
{
childHeight = layoutHeight;
childWidth = (int)(((float)layoutHeight / (float)intHeight) * intWidth);
}
for (int i =0 ; i < ChildCount; i++ )
{
GetChildAt(i).Layout(0, 0, childWidth, childHeight);
}
try
{
startIfReady();
}
catch (Exception e)
{
Log.Debug("Something went wrong", e.ToString());
}
}
private class SurfaceCallback : ISurfaceHolderCallback
{
public IntPtr Handle => throw new NotImplementedException();
public void Dispose()
{
}
public void SurfaceChanged(ISurfaceHolder holder, [GeneratedEnum] Format format, int width, int height)
{
}
public void SurfaceCreated(ISurfaceHolder holder)
{
Instance.mSurfaceAvaialbe = true;
try
{
Instance.startIfReady();
}
catch (Exception e)
{
Log.Debug("Something went wrong",e.ToString());
}
}
public void SurfaceDestroyed(ISurfaceHolder holder)
{
Instance.mSurfaceAvaialbe = false;
}
}
}
}
GraphicOverlay
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Gms.Vision;
using Android.Util;
using Android.Graphics;
using Java.Util;
namespace StockApp.UI
{
[Register("stockapp.stockapp.ui.GraphicOverlay")]
class GraphicOverlay<T> : View where T: GraphicOverlay<T>.Graphic
{
public T tT ;
private Object mLock = new object();
private int mPreviewWidth { get; set; }
private float mWidthScaleFactor { get; set; } = 1.0f;
private int mPreviewHeight;
private float mHeightScaleFactor { get; set; } = 1.0f;
private int mFacing { get; set; } = (int)CameraFacing.Back;
private HashSet<T> mGraphics = new HashSet<T>();
public GraphicOverlay(Context context, IAttributeSet attrs)
: base(context, attrs)
{
}
public void Clear()
{
lock(mLock)
{
mGraphics.Clear();
}
}
public void Add(T graphic)
{
lock(mLock)
{
mGraphics.Add(graphic);
}
PostInvalidate();
}
public void Remove(T graphic)
{
lock(mLock)
{
mGraphics.Remove(graphic);
}
PostInvalidate();
}
public List<T> getGraphics()
{
lock(mLock)
{
return mGraphics.ToList();
}
}
public void setCameraInfo(int previewWidth, int previewHeight, int facing)
{
lock(mLock)
{
mPreviewHeight = previewHeight;
mPreviewWidth = previewWidth;
mFacing = facing;
}
PostInvalidate();
}
protected void onDraw(Canvas canvas)
{
base.OnDraw(canvas);
lock(mLock)
{
if(mPreviewWidth !=0 && mPreviewHeight !=0)
{
mWidthScaleFactor = (float)canvas.Width / (float)mPreviewWidth;
mHeightScaleFactor = (float)canvas.Height / (float)mPreviewHeight;
}
foreach (Graphic graphic in mGraphics)
{
graphic.Draw(canvas);
}
}
}
public abstract class Graphic
{
private GraphicOverlay<T> mOverlay;
public Graphic(GraphicOverlay<T> overlay)
{
mOverlay = overlay;
}
public abstract void Draw(Canvas canvas);
public float scaleX(float horizontal) { return horizontal * mOverlay.mWidthScaleFactor; }
public float scaleY(float vertical) { return vertical * mOverlay.mHeightScaleFactor; }
public float translateX(float x)
{
float scale = scaleX(x);
if(mOverlay.mFacing == (int)CameraFacing.Front)
{
return mOverlay.Width - scale;
}
else
{
return scale;
}
}
public float translateY(float y) { return scaleY(y); }
public void postInvalidate() { mOverlay.PostInvalidate(); }
}
}
}