2017-01-03 9 views
2

내 레이아웃 코드.Xamarin.Android에서 표면 뷰 높이를 변경하는 방법은 무엇입니까?

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:app="http://schemas.android.com/apk/res-auto" 
xmlns:tools="http://schemas.android.com/tools" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
tools:showIn="@layout/Main"> 
<LinearLayout 
    android:id="@+id/camera_ll" 
    android:layout_height="match_parent" 
    android:layout_width="match_parent" 
    android:weightSum="100" 
    android:orientation="vertical"> 
    <FrameLayout 
     android:layout_height="0dp" 
     android:layout_width="match_parent" 
     android:id="@+id/frameLayout" 
     android:layout_weight="90" /> 
    <Button 
     android:layout_height="0dp" 
     android:layout_width="match_parent" 
     android:id="@+id/btn_capture" 
     android:text="Scan Answer Sheet" 
     fontPath="Fonts/Verb-Semibold.otf" 
     android:textColor="@android:color/white" 
     android:background="@drawable/bttn_green" 
     android:layout_weight="10" /> 
    </LinearLayout> 
    </RelativeLayout> 

내 Java 코드입니다.

public class CameraPreview : Activity, Android.Hardware.Camera.IPictureCallback, Android.Hardware.Camera.IPreviewCallback, Android.Hardware.Camera.IShutterCallback 
{ 
    String PICTURE_FILENAME = "picture.jpg"; 
    Preview mPreview; 
    Camera mCamera; 
    int numberOfCameras; 
    int cameraCurrentlyLocked; 

    // The first rear facing camera 
    int defaultCameraId; 
    FrameLayout frameLayout; 
    Button btn_capture; 
    protected override void OnCreate(Bundle savedInstanceState) 
    { 
     base.OnCreate(savedInstanceState); 

     // Hide the window title and go fullscreen. 
     RequestWindowFeature(WindowFeatures.NoTitle); 
     Window.AddFlags(WindowManagerFlags.Fullscreen); 

     // Create our Preview view and set it as the content of our activity. 

     SetContentView(Resource.Layout.CameraPriview); 
     frameLayout = FindViewById<FrameLayout>(Resource.Id.frameLayout); 
     btn_capture = FindViewById<Button>(Resource.Id.btn_capture); 
     mPreview = new Preview(this, frameLayout); 
     frameLayout.AddView(mPreview); 
     btn_capture.Click += TakeAPicture; 
     // Find the total number of cameras available 
     numberOfCameras = Camera.NumberOfCameras; 

     // Find the ID of the default camera 
     Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); 
     for (int i = 0; i < numberOfCameras; i++) 
     { 
      Camera.GetCameraInfo(i, cameraInfo); 
      if (cameraInfo.Facing == CameraFacing.Back) 
      { 
       defaultCameraId = i; 
      } 
     } 
    } 
    private void TakeAPicture(object sender, EventArgs eventArgs) 
    { 

     Android.Hardware.Camera.Parameters p = mCamera.GetParameters(); 
     p.PictureFormat = Android.Graphics.ImageFormatType.Jpeg; 
     mCamera.SetParameters(p); 
     mCamera.TakePicture(this, this, this); 

    } 
    void Camera.IPictureCallback.OnPictureTaken(byte[] data, Android.Hardware.Camera camera) 
    { 
     FileOutputStream outStream = null; 
     File dataDir = Android.OS.Environment.ExternalStorageDirectory; 
     if (data != null) 
     { 
      try 
      { 
       outStream = new FileOutputStream(dataDir + "/" + PICTURE_FILENAME); 
       outStream.Write(data); 
       outStream.Close(); 
      } 
      catch (FileNotFoundException e) 
      { 
       System.Console.Out.WriteLine(e.Message); 
      } 
      catch (IOException ie) 
      { 
       System.Console.Out.WriteLine(ie.Message); 
      } 
     } 
    } 

    void Camera.IPreviewCallback.OnPreviewFrame(byte[] b, Android.Hardware.Camera c) 
    { 

    } 

    void Camera.IShutterCallback.OnShutter() 
    { 

    } 
    protected override void OnResume() 
    { 
     base.OnResume(); 

     // Open the default i.e. the first rear facing camera. 
     mCamera = Camera.Open(); 
     cameraCurrentlyLocked = defaultCameraId; 
     mPreview.PreviewCamera = mCamera; 
     mCamera.SetDisplayOrientation(90); 



    } 


    protected override void OnPause() 
    { 
     base.OnPause(); 

     // Because the Camera object is a shared resource, it's very 
     // important to release it when the activity is paused. 
     if (mCamera != null) 
     { 
      mPreview.PreviewCamera = null; 
      mCamera.Release(); 
      mCamera = null; 
     } 
    } 

    public override bool OnCreateOptionsMenu(IMenu menu) 
    { 
     // Inflate our menu which can gather user input for switching camera 
     //MenuInflater.Inflate(Resource.Menu.camera_menu, menu); 
     return true; 
    } 


} 

표면보기 코드.

class Preview : ViewGroup, ISurfaceHolderCallback 
{ 
    string TAG = "Preview"; 
    FrameLayout f; 
    SurfaceView mSurfaceView; 
    ISurfaceHolder mHolder; 
    Camera.Size mPreviewSize; 
    IList<Camera.Size> mSupportedPreviewSizes; 
    Camera _camera; 

    public Camera PreviewCamera 
    { 
     get { return _camera; } 
     set 
     { 
      _camera = value; 
      if (_camera != null) 
      { 
       mSupportedPreviewSizes = PreviewCamera.GetParameters().SupportedPreviewSizes; 
       RequestLayout(); 
      } 
     } 
    } 

    public Preview(Context context, FrameLayout f) : base(context) 
    { 
     this.f = f; 
     mSurfaceView = new SurfaceView(context); 
     AddView(mSurfaceView); 

     // Install a SurfaceHolder.Callback so we get notified when the 
     // underlying surface is created and destroyed. 
     mHolder = mSurfaceView.Holder; 
     mHolder.AddCallback(this); 
     mHolder.SetType(SurfaceType.PushBuffers); 

    } 

    public void SwitchCamera(Camera camera) 
    { 
     PreviewCamera = camera; 

     try 
     { 
      camera.SetPreviewDisplay(mHolder); 
     } 
     catch (Java.IO.IOException exception) 
     { 
      Log.Error(TAG, "IOException caused by setPreviewDisplay()", exception); 
     } 

     Camera.Parameters parameters = camera.GetParameters(); 
     parameters.SetPreviewSize(mPreviewSize.Width, mPreviewSize.Height); 

     RequestLayout(); 

     camera.SetParameters(parameters); 
    } 

    protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec) 
    { 
     // We purposely disregard child measurements because act as a 
     // wrapper to a SurfaceView that centers the camera preview instead 
     // of stretching it. 
     int width = ResolveSize(SuggestedMinimumWidth, widthMeasureSpec); 
     int height = ResolveSize(SuggestedMinimumHeight, heightMeasureSpec); 
     SetMeasuredDimension(width, height); 

     if (mSupportedPreviewSizes != null) 
     { 
      mPreviewSize = GetOptimalPreviewSize(mSupportedPreviewSizes, width, height); 
     } 
    } 

    protected override void OnLayout(bool changed, int l, int t, int r, int b) 
    { 
     if (changed && ChildCount > 0) 
     { 
      View child = GetChildAt(0); 

      int width = r - l; 
      int height = b - t; 

      int previewWidth = width; 
      int previewHeight = height; 
      if (mPreviewSize != null) 
      { 
       previewWidth = mPreviewSize.Width; 
       previewHeight = mPreviewSize.Height; 
      } 

      // Center the child SurfaceView within the parent. 
      if (width * previewHeight > height * previewWidth) 
      { 
       int scaledChildWidth = previewWidth * height/previewHeight; 
       child.Layout((width - scaledChildWidth)/2, 0, 
          (width + scaledChildWidth)/2, height); 
      } 
      else 
      { 
       int scaledChildHeight = previewHeight * width/previewWidth; 
       child.Layout(0, (height - scaledChildHeight)/2, 
          width, (height + scaledChildHeight)/2); 
      } 
     } 
    } 

    public void SurfaceCreated(ISurfaceHolder holder) 
    { 
     // The Surface has been created, acquire the camera and tell it where 
     // to draw. 
     try 
     { 
      if (PreviewCamera != null) 
      { 

       PreviewCamera.SetPreviewDisplay(holder); 

      } 
     } 
     catch (Java.IO.IOException exception) 
     { 
      Log.Error(TAG, "IOException caused by setPreviewDisplay()", exception); 
     } 
    } 

    public void SurfaceDestroyed(ISurfaceHolder holder) 
    { 
     // Surface will be destroyed when we return, so stop the preview. 
     if (PreviewCamera != null) 
     { 
      PreviewCamera.StopPreview(); 
     } 
    } 

    private Camera.Size GetOptimalPreviewSize(IList<Camera.Size> sizes, int w, int h) 
    { 
     const double ASPECT_TOLERANCE = 0.1; 
     double targetRatio = (double)w/h; 

     if (sizes == null) 
      return null; 

     Camera.Size optimalSize = null; 
     double minDiff = Double.MaxValue; 

     int targetHeight = h; 

     // Try to find an size match aspect ratio and size 
     foreach (Camera.Size size in sizes) 
     { 
      double ratio = (double)size.Width/size.Height; 

      if (Math.Abs(ratio - targetRatio) > ASPECT_TOLERANCE) 
       continue; 

      if (Math.Abs(size.Height - targetHeight) < minDiff) 
      { 
       optimalSize = size; 
       minDiff = Math.Abs(size.Height - targetHeight); 
      } 
     } 

     // Cannot find the one match the aspect ratio, ignore the requirement 
     if (optimalSize == null) 
     { 
      minDiff = Double.MaxValue; 
      foreach (Camera.Size size in sizes) 
      { 
       if (Math.Abs(size.Height - targetHeight) < minDiff) 
       { 
        optimalSize = size; 
        minDiff = Math.Abs(size.Height - targetHeight); 
       } 
      } 
     } 


     return optimalSize; 
    } 

    public void SurfaceChanged(ISurfaceHolder holder, Android.Graphics.Format format, int w, int h) 
    { 
     // Now that the size is known, set up the camera parameters and begin 
     // the preview. 
     Camera.Parameters parameters = PreviewCamera.GetParameters(); 
     parameters.SetPreviewSize(mPreviewSize.Width, mPreviewSize.Height); 
     RequestLayout(); 

     PreviewCamera.SetParameters(parameters); 
     PreviewCamera.StartPreview(); 
    } 


} 

출력 :

enter image description here

지금 내가 나를 위해 일하는 모든 사용 가능한 공간만을 채우기 위해 카메라의 높이를 증가합니다. 누구든지 솔루션을 알면 감사합니다.

+0

어떤 Android API 수준을 타겟팅하고 있습니까? –

+0

KitKat (4.4.4)에서 테스트 중이며 최신 –

답변

1

이제는 카메라의 높이를 늘려 사용 가능한 공간을 모두 채우고 싶지만 나에게 맞는 것은 없습니다. 누구든지 솔루션을 알면 감사합니다.

미리보기 크기의 설정 코드

Preview에있다 '의 OnLayout 방법 : 여기

protected override void OnLayout(bool changed, int l, int t, int r, int b) 
{ 
    if (changed && ChildCount > 0) 
    { 
     View child = GetChildAt(0); 

     int width = r - l; 
     int height = b - t; 

     int previewWidth = width; 
     int previewHeight = height; 
     if (mPreviewSize != null) 
     { 
      previewWidth = mPreviewSize.Width; 
      previewHeight = mPreviewSize.Height; 
     } 

     // Center the child SurfaceView within the parent. 
     if (width * previewHeight > height * previewWidth) 
     { 
      int scaledChildWidth = previewWidth * height/previewHeight; 
      child.Layout((width - scaledChildWidth)/2, 0, 
         (width + scaledChildWidth)/2, height); 
     } 
     else 
     { 
      int scaledChildHeight = previewHeight * width/previewWidth; 
      child.Layout(0, (height - scaledChildHeight)/2, 
         width, (height + scaledChildHeight)/2); 
     } 
    } 
} 

내가 코드하지 않는'의 의미를. 그러나 child.Layout(0, (height - scaledChildHeight)/2,width, (height + scaledChildHeight)/2);에 의해 미리보기 창의 상단 경계와 하단 경계가 (height - scaledChildHeight)/2(height + scaledChildHeight)/2)으로 감소합니다.

카메라 높이를 늘려 사용 가능한 공간을 모두 채우려면이 코드 단편을 수정해야합니다. 예 :

int LeftBoundary=0,TopBoundary=0; 
int RightBoundary=r,BottomBoundary=b; 
child.Layout(LeftBoundary,TopBoundary,RightBoundary,BottomBoundary)); 
+0

을 대상으로합니다. 감사합니다. @Elvis Xia - MSFT가 지금 당신의 도움으로 작업 중입니다. –

+0

문제가 해결되었음을 알리게되어 대단히 기쁩니다. –

+0

위 코드가 작동합니다. 4.4.4로 좋았지 만 마쉬 멜로우 6.0.1에 검은 화면이 생겼다. 나를 안내해 줄 수 있니? –