ঠিক আছে, তাই আমি মনে করি সাধারণ ক্যামেরা প্রিভিউ প্রসারিত সমস্যার জন্য পর্যাপ্ত উত্তর নেই । বা কমপক্ষে আমি একটিও পাইনি। আমার অ্যাপ্লিকেশনটিও এই স্ট্রেচিং সিনড্রোমের ক্ষতি করেছে এবং এই পোর্টাল এবং ইন্টারনেটের সমস্ত ব্যবহারকারীর উত্তরগুলির একসাথে সমাধান পেতে আমার কিছুটা সময় নিয়েছিল।
আমি @ হেসামের সমাধানটি চেষ্টা করেছি কিন্তু এটি কার্যকর হয়নি এবং আমার ক্যামেরার পূর্বরূপটি মূলত বিকৃত করে ফেলেছে।
প্রথমে আমি আমার সমাধানের কোডটি দেখি (কোডটির গুরুত্বপূর্ণ অংশগুলি) এবং তারপরে আমি কেন এই পদক্ষেপ নিয়েছি তা ব্যাখ্যা করি। কর্মক্ষমতা পরিবর্তনের জন্য জায়গা আছে।
প্রধান ক্রিয়াকলাপ এক্সএমএল লেআউট:
<RelativeLayout
android:id="@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<FrameLayout
android:id="@+id/camera_preview"
android:layout_centerInParent="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
ক্যামেরার পূর্বরূপ:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder prHolder;
private Camera prCamera;
public List<Camera.Size> prSupportedPreviewSizes;
private Camera.Size prPreviewSize;
@SuppressWarnings("deprecation")
public YoCameraPreview(Context context, Camera camera) {
super(context);
prCamera = camera;
prSupportedPreviewSizes = prCamera.getParameters().getSupportedPreviewSizes();
prHolder = getHolder();
prHolder.addCallback(this);
prHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
try {
prCamera.setPreviewDisplay(holder);
prCamera.startPreview();
} catch (IOException e) {
Log.d("Yologram", "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (prHolder.getSurface() == null){
return;
}
try {
prCamera.stopPreview();
} catch (Exception e){
}
try {
Camera.Parameters parameters = prCamera.getParameters();
List<String> focusModes = parameters.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
}
parameters.setPreviewSize(prPreviewSize.width, prPreviewSize.height);
prCamera.setParameters(parameters);
prCamera.setPreviewDisplay(prHolder);
prCamera.startPreview();
} catch (Exception e){
Log.d("Yologram", "Error starting camera preview: " + e.getMessage());
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if (prSupportedPreviewSizes != null) {
prPreviewSize =
getOptimalPreviewSize(prSupportedPreviewSizes, width, height);
}
}
public Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) h / w;
if (sizes == null)
return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : 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);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
}
যথোপযুক্ত সৃষ্টিকর্তা:
public class MainActivity extends Activity {
...
@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
maCamera = getCameraInstance();
maLayoutPreview = (FrameLayout) findViewById(R.id.camera_preview);
maPreview = new CameraPreview(this, maCamera);
Point displayDim = getDisplayWH();
Point layoutPreviewDim = calcCamPrevDimensions(displayDim,
maPreview.getOptimalPreviewSize(maPreview.prSupportedPreviewSizes,
displayDim.x, displayDim.y));
if (layoutPreviewDim != null) {
RelativeLayout.LayoutParams layoutPreviewParams =
(RelativeLayout.LayoutParams) maLayoutPreview.getLayoutParams();
layoutPreviewParams.width = layoutPreviewDim.x;
layoutPreviewParams.height = layoutPreviewDim.y;
layoutPreviewParams.addRule(RelativeLayout.CENTER_IN_PARENT);
maLayoutPreview.setLayoutParams(layoutPreviewParams);
}
maLayoutPreview.addView(maPreview);
}
@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
private Point getDisplayWH() {
Display display = this.getWindowManager().getDefaultDisplay();
Point displayWH = new Point();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
display.getSize(displayWH);
return displayWH;
}
displayWH.set(display.getWidth(), display.getHeight());
return displayWH;
}
private Point calcCamPrevDimensions(Point disDim, Camera.Size camDim) {
Point displayDim = disDim;
Camera.Size cameraDim = camDim;
double widthRatio = (double) displayDim.x / cameraDim.width;
double heightRatio = (double) displayDim.y / cameraDim.height;
// use ">" to zoom preview full screen
if (widthRatio < heightRatio) {
Point calcDimensions = new Point();
calcDimensions.x = displayDim.x;
calcDimensions.y = (displayDim.x * cameraDim.height) / cameraDim.width;
return calcDimensions;
}
// use "<" to zoom preview full screen
if (widthRatio > heightRatio) {
Point calcDimensions = new Point();
calcDimensions.x = (displayDim.y * cameraDim.width) / cameraDim.height;
calcDimensions.y = displayDim.y;
return calcDimensions;
}
return null;
}
}
আমার ভাষ্য:
সব এই বিন্দু যে যদিও আপনি নিরূপণ হয় অনুকূল ক্যামেরা আকার মধ্যে getOptimalPreviewSize()
আপনি শুধুমাত্র বাছাই নিকটতম অনুপাত আপনার পর্দা মাপসই। সুতরাং অনুপাতটি ঠিক একইরূপে না হলে পূর্বরূপটি প্রসারিত হবে।
কেন এটি প্রসারিত হবে? আপনার FrameLayout ক্যামেরা প্রিভিউ সেট করা হয় কারণ layout.xml করার match_parent প্রস্থ ও উচ্চতা হবে। এজন্য পূর্বরূপ পুরো পর্দায় প্রসারিত হবে।
যা করা দরকার তা হল নির্বাচিত ক্যামেরার আকারের অনুপাতের সাথে মেলে ক্যামেরার পূর্বরূপ বিন্যাসের প্রস্থ এবং উচ্চতা নির্ধারণ করা , যাতে পূর্বরূপটি তার অনুপাতের অনুপাত রাখে এবং বিকৃত করে না।
আমি CameraPreview
সমস্ত গণনা এবং লেআউট পরিবর্তনগুলি করার জন্য ক্লাসটি ব্যবহার করার চেষ্টা করেছি , তবে আমি এটি বের করতে পারি না। আমি এই সমাধানটি প্রয়োগ করার চেষ্টা করেছি , কিন্তু SurfaceView
চিনতে পারি না getChildCount ()
বা করি না getChildAt (int index)
। আমি মনে করি, শেষ পর্যন্ত একটি রেফারেন্স সহ এটি কাজ করেছিলাম maLayoutPreview
, তবে এটি ছিল খারাপ আচরণ এবং সেটটিকে আমার সম্পূর্ণ অ্যাপ্লিকেশনে প্রয়োগ করে এবং প্রথম ছবি তোলার পরে এটি হয়েছিল। সুতরাং আমি এটি যেতে দিয়েছিলাম এবং লেআউট পরিবর্তনগুলিতে সরানো হয়েছে MainActivity
।
ইন CameraPreview
আমি পরিবর্তন prSupportedPreviewSizes
এবং getOptimalPreviewSize()
করতে প্রকাশ্য তাই আমি এটা ব্যবহার করতে পারেন MainActivity
। তারপরে আমার প্রদর্শনের মাত্রা প্রয়োজন (মাইনাস নেভিগেশন / স্ট্যাটাস বার যদি থাকে তবে) এবং সর্বোত্তম ক্যামেরার আকার বেছে নেওয়া উচিত । আমি ডিসপ্লে আকারের পরিবর্তে রিলেটিভলআউট (বা ফ্রেমলআউট) আকার পাওয়ার চেষ্টা করেছি, তবে এটি শূন্যের মান ফিরে আসছিল। এই সমাধানটি আমার পক্ষে কার্যকর হয়নি। বিন্যাসটির পরে এর মান পেল onWindowFocusChanged
(লগ ইন চেক করা)।
সুতরাং নির্বাচিত ক্যামেরার আকারের অনুপাতের সাথে মেলে লেআউটটির মাত্রা গণনা করার জন্য আমার কাছে আমার পদ্ধতি রয়েছে। এখন আপনাকে কেবল LayoutParams
আপনার ক্যামেরা প্রিভিউ লেআউট সেট করতে হবে । প্রস্থ, উচ্চতা পরিবর্তন করুন এবং এটি প্যারেন্টে কেন্দ্র করুন।
প্রাকদর্শন মাত্রা গণনা করার জন্য দুটি পছন্দ রয়েছে are হয় আপনি এটিকে পাশের বা উপরে / নীচে কালো বারগুলি (যদি উইন্ডোব্যাকগ্রাউন্ডটি নালায় সেট করা থাকে) দিয়ে পর্দা ফিট করতে চান । অথবা আপনি পূর্বদর্শনটি পুরো স্ক্রিনে জুম করাতে চান । আমি আরও তথ্য মন্তব্য মন্তব্য calcCamPrevDimensions()
।