New demo app (#53)

* New demo app

* UI fixes

* Refactor preview activities

* Add gestures control
pull/54/head
Mattia Iavarone 7 years ago committed by GitHub
parent f8d38e3c8c
commit 5964080db4
  1. 3
      demo/build.gradle
  2. 2
      demo/src/main/AndroidManifest.xml
  3. 39
      demo/src/main/java/com/otaliastudios/cameraview/demo/AutoUnfocusEditText.java
  4. 211
      demo/src/main/java/com/otaliastudios/cameraview/demo/CameraActivity.java
  5. 176
      demo/src/main/java/com/otaliastudios/cameraview/demo/Control.java
  6. 103
      demo/src/main/java/com/otaliastudios/cameraview/demo/ControlView.java
  7. 375
      demo/src/main/java/com/otaliastudios/cameraview/demo/MainActivity.java
  8. 50
      demo/src/main/java/com/otaliastudios/cameraview/demo/MessageView.java
  9. 38
      demo/src/main/java/com/otaliastudios/cameraview/demo/PicturePreviewActivity.java
  10. 24
      demo/src/main/java/com/otaliastudios/cameraview/demo/VideoPreviewActivity.java
  11. 8
      demo/src/main/res/drawable/background.xml
  12. 2
      demo/src/main/res/drawable/ic_edit.xml
  13. 100
      demo/src/main/res/layout/activity_camera.xml
  14. 555
      demo/src/main/res/layout/activity_main.xml
  15. 161
      demo/src/main/res/layout/activity_picture_preview.xml
  16. 45
      demo/src/main/res/layout/activity_video_preview.xml
  17. 31
      demo/src/main/res/layout/control_view.xml
  18. 8
      demo/src/main/res/layout/spinner_text.xml
  19. 2
      demo/src/main/res/values/colors.xml
  20. 8
      demo/src/main/res/values/styles.xml

@ -23,6 +23,5 @@ android {
dependencies { dependencies {
compile project(':cameraview') compile project(':cameraview')
compile "com.android.support:appcompat-v7:$supportLibVersion" compile "com.android.support:appcompat-v7:$supportLibVersion"
compile 'com.jakewharton:butterknife:8.4.0' compile "com.android.support:design:$supportLibVersion"
annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'
} }

@ -13,7 +13,7 @@
android:theme="@style/AppTheme"> android:theme="@style/AppTheme">
<activity <activity
android:name=".MainActivity" android:name=".CameraActivity"
android:theme="@style/Theme.MainActivity" android:theme="@style/Theme.MainActivity"
android:configChanges="orientation|screenLayout|keyboardHidden"> android:configChanges="orientation|screenLayout|keyboardHidden">
<intent-filter> <intent-filter>

@ -1,39 +0,0 @@
package com.otaliastudios.cameraview.demo;
import android.content.Context;
import android.support.v7.widget.AppCompatEditText;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.inputmethod.InputMethodManager;
public class AutoUnfocusEditText extends AppCompatEditText {
public AutoUnfocusEditText(Context context) {
super(context);
}
public AutoUnfocusEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AutoUnfocusEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
closeKeyboard();
clearFocus();
return true;
}
return super.dispatchKeyEvent(event);
}
private void closeKeyboard() {
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getWindowToken(), 0);
}
}

@ -0,0 +1,211 @@
package com.otaliastudios.cameraview.demo;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomSheetBehavior;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.Toast;
import com.otaliastudios.cameraview.Audio;
import com.otaliastudios.cameraview.CameraListener;
import com.otaliastudios.cameraview.CameraLogger;
import com.otaliastudios.cameraview.CameraOptions;
import com.otaliastudios.cameraview.CameraView;
import com.otaliastudios.cameraview.Flash;
import com.otaliastudios.cameraview.Grid;
import com.otaliastudios.cameraview.SessionType;
import com.otaliastudios.cameraview.Size;
import com.otaliastudios.cameraview.VideoQuality;
import com.otaliastudios.cameraview.WhiteBalance;
import java.io.File;
public class CameraActivity extends AppCompatActivity implements View.OnClickListener, ControlView.Callback {
private CameraView camera;
private ViewGroup controlPanel;
private boolean mCapturingPicture;
private boolean mCapturingVideo;
// To show stuff in the callback
private Size mCaptureNativeSize;
private long mCaptureTime;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
CameraLogger.setLogLevel(CameraLogger.LEVEL_VERBOSE);
camera = findViewById(R.id.camera);
camera.addCameraListener(new CameraListener() {
public void onCameraOpened(CameraOptions options) { onOpened(); }
public void onPictureTaken(byte[] jpeg) { onPicture(jpeg); }
public void onVideoTaken(File video) { onVideo(video); }
});
findViewById(R.id.edit).setOnClickListener(this);
findViewById(R.id.capturePhoto).setOnClickListener(this);
findViewById(R.id.captureVideo).setOnClickListener(this);
findViewById(R.id.toggleCamera).setOnClickListener(this);
controlPanel = findViewById(R.id.controls);
ViewGroup group = (ViewGroup) controlPanel.getChildAt(0);
Control[] controls = Control.values();
for (Control control : controls) {
ControlView view = new ControlView(this, control, this);
group.addView(view, ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
controlPanel.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
BottomSheetBehavior b = BottomSheetBehavior.from(controlPanel);
b.setState(BottomSheetBehavior.STATE_HIDDEN);
}
});
}
private void message(String content, boolean important) {
int length = important ? Toast.LENGTH_LONG : Toast.LENGTH_SHORT;
Toast.makeText(this, content, length).show();
}
private void onOpened() {
ViewGroup group = (ViewGroup) controlPanel.getChildAt(0);
for (int i = 0; i < group.getChildCount(); i++) {
ControlView view = (ControlView) group.getChildAt(i);
view.onCameraOpened(camera);
}
}
private void onPicture(byte[] jpeg) {
mCapturingPicture = false;
long callbackTime = System.currentTimeMillis();
if (mCapturingVideo) {
message("Captured while taking video. Size="+mCaptureNativeSize, false);
return;
}
// This can happen if picture was taken with a gesture.
if (mCaptureTime == 0) mCaptureTime = callbackTime - 300;
if (mCaptureNativeSize == null) mCaptureNativeSize = camera.getCaptureSize();
PicturePreviewActivity.setImage(jpeg);
Intent intent = new Intent(CameraActivity.this, PicturePreviewActivity.class);
intent.putExtra("delay", callbackTime - mCaptureTime);
intent.putExtra("nativeWidth", mCaptureNativeSize.getWidth());
intent.putExtra("nativeHeight", mCaptureNativeSize.getHeight());
startActivity(intent);
mCaptureTime = 0;
mCaptureNativeSize = null;
}
private void onVideo(File video) {
mCapturingVideo = false;
Intent intent = new Intent(CameraActivity.this, VideoPreviewActivity.class);
intent.putExtra("video", Uri.fromFile(video));
startActivity(intent);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.edit: edit(); break;
case R.id.capturePhoto: capturePhoto(); break;
case R.id.captureVideo: captureVideo(); break;
case R.id.toggleCamera: toggleCamera(); break;
}
}
private void edit() {
BottomSheetBehavior b = BottomSheetBehavior.from(controlPanel);
b.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
private void capturePhoto() {
if (mCapturingPicture) return;
mCapturingPicture = true;
mCaptureTime = System.currentTimeMillis();
mCaptureNativeSize = camera.getCaptureSize();
message("Capturing picture...", false);
camera.capturePicture();
}
private void captureVideo() {
if (camera.getSessionType() != SessionType.VIDEO) {
message("Can't record video while session type is 'picture'.", false);
return;
}
if (mCapturingPicture || mCapturingVideo) return;
mCapturingVideo = true;
message("Recording for 8 seconds...", true);
camera.startCapturingVideo(null, 8000);
}
private void toggleCamera() {
if (mCapturingPicture) return;
switch (camera.toggleFacing()) {
case BACK:
message("Switched to back camera!", false);
break;
case FRONT:
message("Switched to front camera!", false);
break;
}
}
@Override
public void onValueChanged(Control control, Object value, String name) {
control.applyValue(camera, value);
BottomSheetBehavior b = BottomSheetBehavior.from(controlPanel);
b.setState(BottomSheetBehavior.STATE_HIDDEN);
message("Changed " + control.getName() + " to " + name, false);
}
//region Boilerplate
@Override
protected void onResume() {
super.onResume();
camera.start();
}
@Override
protected void onPause() {
super.onPause();
camera.stop();
}
@Override
protected void onDestroy() {
super.onDestroy();
camera.destroy();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
boolean valid = true;
for (int grantResult : grantResults) {
valid = valid && grantResult == PackageManager.PERMISSION_GRANTED;
}
if (valid && !camera.isStarted()) {
camera.start();
}
}
//endregion
}

@ -0,0 +1,176 @@
package com.otaliastudios.cameraview.demo;
import android.view.View;
import android.view.ViewGroup;
import com.otaliastudios.cameraview.Audio;
import com.otaliastudios.cameraview.CameraOptions;
import com.otaliastudios.cameraview.CameraView;
import com.otaliastudios.cameraview.Flash;
import com.otaliastudios.cameraview.Gesture;
import com.otaliastudios.cameraview.GestureAction;
import com.otaliastudios.cameraview.Grid;
import com.otaliastudios.cameraview.SessionType;
import com.otaliastudios.cameraview.VideoQuality;
import com.otaliastudios.cameraview.WhiteBalance;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
* Controls that we want to display in a ControlView.
*/
public enum Control {
WIDTH("Width", false),
HEIGHT("Height", true),
SESSION("Session type", false),
CROP_OUTPUT("Crop output", true),
FLASH("Flash", false),
WHITE_BALANCE("White balance", false),
GRID("Grid", true),
VIDEO_QUALITY("Video quality", false),
AUDIO("Audio", true),
PINCH("Pinch gesture", false),
HSCROLL("Horizontal scroll gesture", false),
VSCROLL("Vertical scroll gesture", false),
TAP("Single tap gesture", false),
LONG_TAP("Long tap gesture", true);
private String name;
private boolean last;
Control(String n, boolean l) {
name = n;
last = l;
}
public String getName() {
return name;
}
public boolean isSectionLast() {
return last;
}
public Collection<?> getValues(CameraView view) {
CameraOptions options = view.getCameraOptions();
switch (this) {
case WIDTH:
case HEIGHT:
View root = (View) view.getParent();
ArrayList<Integer> list = new ArrayList<>();
int boundary = this == WIDTH ? root.getWidth() : root.getHeight();
if (boundary == 0) boundary = 1000;
int step = boundary / 10;
list.add(ViewGroup.LayoutParams.WRAP_CONTENT);
list.add(ViewGroup.LayoutParams.MATCH_PARENT);
for (int i = step; i < boundary; i += step) {
list.add(i);
}
return list;
case SESSION: return Arrays.asList(SessionType.values());
case CROP_OUTPUT: return Arrays.asList(true, false);
case FLASH: return options.getSupportedFlash();
case WHITE_BALANCE: return options.getSupportedWhiteBalance();
case GRID: return Arrays.asList(Grid.values());
case VIDEO_QUALITY: return Arrays.asList(VideoQuality.values());
case AUDIO: return Arrays.asList(Audio.values());
case PINCH:
case HSCROLL:
case VSCROLL:
ArrayList<GestureAction> list1 = new ArrayList<>();
addIfSupported(options, list1, GestureAction.NONE);
addIfSupported(options, list1, GestureAction.ZOOM);
addIfSupported(options, list1, GestureAction.EXPOSURE_CORRECTION);
return list1;
case TAP:
case LONG_TAP:
ArrayList<GestureAction> list2 = new ArrayList<>();
addIfSupported(options, list2, GestureAction.NONE);
addIfSupported(options, list2, GestureAction.CAPTURE);
addIfSupported(options, list2, GestureAction.FOCUS);
addIfSupported(options, list2, GestureAction.FOCUS_WITH_MARKER);
return list2;
}
return null;
}
private void addIfSupported(CameraOptions options, List<GestureAction> list, GestureAction value) {
if (options.supports(value)) list.add(value);
}
public Object getCurrentValue(CameraView view) {
switch (this) {
case WIDTH: return view.getLayoutParams().width;
case HEIGHT: return view.getLayoutParams().height;
case SESSION: return view.getSessionType();
case CROP_OUTPUT: return view.getCropOutput();
case FLASH: return view.getFlash();
case WHITE_BALANCE: return view.getWhiteBalance();
case GRID: return view.getGrid();
case VIDEO_QUALITY: return view.getVideoQuality();
case AUDIO: return view.getAudio();
case PINCH: return view.getGestureAction(Gesture.PINCH);
case HSCROLL: return view.getGestureAction(Gesture.SCROLL_HORIZONTAL);
case VSCROLL: return view.getGestureAction(Gesture.SCROLL_VERTICAL);
case TAP: return view.getGestureAction(Gesture.TAP);
case LONG_TAP: return view.getGestureAction(Gesture.LONG_TAP);
}
return null;
}
public void applyValue(CameraView camera, Object value) {
switch (this) {
case WIDTH:
camera.getLayoutParams().width = (int) value;
camera.setLayoutParams(camera.getLayoutParams());
break;
case HEIGHT:
camera.getLayoutParams().height = (int) value;
camera.setLayoutParams(camera.getLayoutParams());
break;
case SESSION:
camera.setSessionType((SessionType) value);
break;
case CROP_OUTPUT:
camera.setCropOutput((boolean) value);
break;
case FLASH:
camera.setFlash((Flash) value);
break;
case WHITE_BALANCE:
camera.setWhiteBalance((WhiteBalance) value);
break;
case GRID:
camera.setGrid((Grid) value);
break;
case VIDEO_QUALITY:
camera.setVideoQuality((VideoQuality) value);
break;
case AUDIO:
camera.setAudio((Audio) value);
break;
case PINCH:
camera.mapGesture(Gesture.PINCH, (GestureAction) value);
break;
case HSCROLL:
camera.mapGesture(Gesture.SCROLL_HORIZONTAL, (GestureAction) value);
break;
case VSCROLL:
camera.mapGesture(Gesture.SCROLL_VERTICAL, (GestureAction) value);
break;
case TAP:
camera.mapGesture(Gesture.TAP, (GestureAction) value);
break;
case LONG_TAP:
camera.mapGesture(Gesture.LONG_TAP, (GestureAction) value);
break;
}
}
}

@ -0,0 +1,103 @@
package com.otaliastudios.cameraview.demo;
import android.annotation.SuppressLint;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TextView;
import com.otaliastudios.cameraview.CameraOptions;
import com.otaliastudios.cameraview.CameraView;
import java.util.ArrayList;
import java.util.Collection;
public class ControlView<Value> extends LinearLayout implements Spinner.OnItemSelectedListener {
interface Callback {
void onValueChanged(Control control, Object value, String name);
}
private Value value;
private ArrayList<Value> values;
private ArrayList<String> valuesStrings;
private Control control;
private Callback callback;
private Spinner spinner;
public ControlView(Context context, Control control, Callback callback) {
super(context);
this.control = control;
this.callback = callback;
setOrientation(VERTICAL);
inflate(context, R.layout.control_view, this);
TextView title = findViewById(R.id.title);
title.setText(control.getName());
View divider = findViewById(R.id.divider);
divider.setVisibility(control.isSectionLast() ? View.VISIBLE : View.GONE);
ViewGroup content = findViewById(R.id.content);
spinner = new Spinner(context, Spinner.MODE_DROPDOWN);
content.addView(spinner);
}
public Value getValue() {
return value;
}
@SuppressWarnings("all")
public void onCameraOpened(CameraView view) {
values = new ArrayList(control.getValues(view));
value = (Value) control.getCurrentValue(view);
valuesStrings = new ArrayList<>();
for (Value value : values) {
valuesStrings.add(stringify(value));
}
if (values.isEmpty()) {
spinner.setOnItemSelectedListener(null);
spinner.setEnabled(false);
spinner.setAlpha(0.8f);
spinner.setAdapter(new ArrayAdapter(getContext(),
R.layout.spinner_text, new String[]{ "Not supported." }));
spinner.setSelection(0, false);
} else {
spinner.setEnabled(true);
spinner.setAlpha(1f);
spinner.setAdapter(new ArrayAdapter(getContext(),
R.layout.spinner_text, valuesStrings));
spinner.setSelection(values.indexOf(value), false);
spinner.setOnItemSelectedListener(this);
}
}
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
if (values.get(i) != value) {
Log.e("ControlView", "curr: " + value + " new: " + values.get(i));
callback.onValueChanged(control, values.get(i), valuesStrings.get(i));
}
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {}
private String stringify(Value value) {
if (value instanceof Integer) {
if ((Integer) value == ViewGroup.LayoutParams.MATCH_PARENT) return "match parent";
if ((Integer) value == ViewGroup.LayoutParams.WRAP_CONTENT) return "wrap content";
}
return String.valueOf(value).replace("_", " ").toLowerCase();
}
}

@ -1,375 +0,0 @@
package com.otaliastudios.cameraview.demo;
import android.content.Intent;
import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;
import com.otaliastudios.cameraview.CameraListener;
import com.otaliastudios.cameraview.CameraLogger;
import com.otaliastudios.cameraview.CameraView;
import com.otaliastudios.cameraview.Grid;
import com.otaliastudios.cameraview.SessionType;
import com.otaliastudios.cameraview.Size;
import com.otaliastudios.cameraview.VideoQuality;
import java.io.File;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class MainActivity extends AppCompatActivity implements View.OnLayoutChangeListener {
@BindView(R.id.activity_main)
ViewGroup parent;
@BindView(R.id.camera)
CameraView camera;
// Capture Mode:
@BindView(R.id.sessionTypeRadioGroup)
RadioGroup sessionTypeRadioGroup;
// Crop Mode:
@BindView(R.id.cropModeRadioGroup)
RadioGroup cropModeRadioGroup;
// Video Quality:
@BindView(R.id.videoQualityRadioGroup)
RadioGroup videoQualityRadioGroup;
// Grid mode:
@BindView(R.id.gridModeRadioGroup)
RadioGroup gridModeRadioGroup;
// Width:
@BindView(R.id.screenWidth)
TextView screenWidth;
@BindView(R.id.width)
EditText width;
@BindView(R.id.widthUpdate)
Button widthUpdate;
@BindView(R.id.widthModeRadioGroup)
RadioGroup widthModeRadioGroup;
// Height:
@BindView(R.id.screenHeight)
TextView screenHeight;
@BindView(R.id.height)
EditText height;
@BindView(R.id.heightUpdate)
Button heightUpdate;
@BindView(R.id.heightModeRadioGroup)
RadioGroup heightModeRadioGroup;
private boolean mCapturingPicture;
private boolean mCapturingVideo;
// To show stuff in the callback
private Size mCaptureNativeSize;
private long mCaptureTime;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
CameraLogger.setLogLevel(CameraLogger.LEVEL_VERBOSE);
parent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
screenWidth.setText("screen: " + parent.getWidth() + "px");
screenHeight.setText("screen: " + parent.getHeight() + "px");
}
});
sessionTypeRadioGroup.setOnCheckedChangeListener(sessionTypeChangedListener);
cropModeRadioGroup.setOnCheckedChangeListener(cropModeChangedListener);
widthModeRadioGroup.setOnCheckedChangeListener(widthModeChangedListener);
heightModeRadioGroup.setOnCheckedChangeListener(heightModeChangedListener);
videoQualityRadioGroup.setOnCheckedChangeListener(videoQualityChangedListener);
gridModeRadioGroup.setOnCheckedChangeListener(gridModeChangedListener);
camera.addOnLayoutChangeListener(this);
camera.addCameraListener(new CameraListener() {
@Override
public void onPictureTaken(byte[] jpeg) {
super.onPictureTaken(jpeg);
mCapturingPicture = false;
long callbackTime = System.currentTimeMillis();
if (mCapturingVideo) {
message("Captured while taking video. Size="+mCaptureNativeSize, false);
return;
}
PicturePreviewActivity.setImage(jpeg);
Intent intent = new Intent(MainActivity.this, PicturePreviewActivity.class);
intent.putExtra("delay", callbackTime - mCaptureTime);
intent.putExtra("nativeWidth", mCaptureNativeSize.getWidth());
intent.putExtra("nativeHeight", mCaptureNativeSize.getHeight());
startActivity(intent);
}
@Override
public void onVideoTaken(File video) {
super.onVideoTaken(video);
mCapturingVideo = false;
Intent intent = new Intent(MainActivity.this, VideoPreviewActivity.class);
intent.putExtra("video", Uri.fromFile(video));
startActivity(intent);
}
});
// Debug location.
/* camera.postDelayed(new Runnable() {
@Override
public void run() {
message("set Location", false);
camera.setLocation(-20, 40.12345);
}
}, 4500); */
}
private void message(String content, boolean important) {
int length = important ? Toast.LENGTH_LONG : Toast.LENGTH_SHORT;
Toast.makeText(this, content, length).show();
}
@Override
protected void onResume() {
super.onResume();
camera.start();
}
@Override
protected void onPause() {
super.onPause();
camera.stop();
}
@Override
protected void onDestroy() {
super.onDestroy();
camera.destroy();
}
@OnClick(R.id.capturePhoto)
void capturePhoto() {
if (mCapturingPicture) return;
mCapturingPicture = true;
mCaptureTime = System.currentTimeMillis();
mCaptureNativeSize = camera.getCaptureSize();
message("Capturing picture...", false);
camera.capturePicture();
}
@OnClick(R.id.captureVideo)
void captureVideo() {
if (camera.getSessionType() != SessionType.VIDEO) {
message("Can't record video while session type is 'picture'.", false);
return;
}
if (mCapturingPicture || mCapturingVideo) return;
mCapturingVideo = true;
message("Recording for 8 seconds...", true);
camera.startCapturingVideo(null, 8000);
}
@OnClick(R.id.toggleCamera)
void toggleCamera() {
if (mCapturingPicture) return;
switch (camera.toggleFacing()) {
case BACK:
message("Switched to back camera!", false);
break;
case FRONT:
message("Switched to front camera!", false);
break;
}
}
@OnClick(R.id.toggleFlash)
void toggleFlash() {
if (mCapturingPicture) return;
switch (camera.toggleFlash()) {
case ON:
message("Flash on!", false);
break;
case OFF:
message("Flash off!", false);
break;
case AUTO:
message("Flash auto!", false);
break;
}
}
RadioGroup.OnCheckedChangeListener sessionTypeChangedListener = new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (mCapturingPicture) return;
boolean pic = checkedId == R.id.sessionTypePicture;
camera.setSessionType(pic ? SessionType.PICTURE : SessionType.VIDEO);
message("Session type set to" + (pic ? " picture!" : " video!"), true);
}
};
RadioGroup.OnCheckedChangeListener cropModeChangedListener = new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (mCapturingPicture) return;
camera.setCropOutput(checkedId == R.id.modeCropVisible);
message("Picture cropping is" + (checkedId == R.id.modeCropVisible ? " on!" : " off!"), false);
}
};
RadioGroup.OnCheckedChangeListener videoQualityChangedListener = new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (mCapturingVideo) return;
VideoQuality videoQuality = VideoQuality.HIGHEST;
switch (checkedId) {
case R.id.videoQualityLowest: videoQuality = VideoQuality.LOWEST; break;
case R.id.videoQualityQvga: videoQuality = VideoQuality.MAX_QVGA; break;
case R.id.videoQuality480p: videoQuality = VideoQuality.MAX_480P; break;
case R.id.videoQuality720p: videoQuality = VideoQuality.MAX_720P; break;
case R.id.videoQuality1080p: videoQuality = VideoQuality.MAX_1080P; break;
case R.id.videoQuality2160p: videoQuality = VideoQuality.MAX_2160P; break;
case R.id.videoQualityHighest: videoQuality = VideoQuality.HIGHEST; break;
}
camera.setVideoQuality(videoQuality);
message("Video quality changed!", false);
}
};
RadioGroup.OnCheckedChangeListener gridModeChangedListener = new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
Grid grid = Grid.OFF;
switch (checkedId) {
case R.id.gridModeOff: grid = Grid.OFF; break;
case R.id.gridMode3x3: grid = Grid.DRAW_3X3; break;
case R.id.gridMode4x4: grid = Grid.DRAW_4X4; break;
case R.id.gridModeGolden: grid = Grid.DRAW_PHI; break;
}
camera.setGrid(grid);
message("Grid mode changed!", false);
}
};
@OnClick(R.id.widthUpdate)
void widthUpdateClicked() {
if (mCapturingPicture) return;
if (widthUpdate.getAlpha() >= 1) {
updateCamera(true, false);
}
}
RadioGroup.OnCheckedChangeListener widthModeChangedListener = new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (mCapturingPicture) return;
widthUpdate.setEnabled(checkedId == R.id.widthCustom);
widthUpdate.setAlpha(checkedId == R.id.widthCustom ? 1f : 0.3f);
width.clearFocus();
width.setEnabled(checkedId == R.id.widthCustom);
width.setAlpha(checkedId == R.id.widthCustom ? 1f : 0.5f);
updateCamera(true, false);
}
};
@OnClick(R.id.heightUpdate)
void heightUpdateClicked() {
if (mCapturingPicture) return;
if (heightUpdate.getAlpha() >= 1) {
updateCamera(false, true);
}
}
RadioGroup.OnCheckedChangeListener heightModeChangedListener = new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (mCapturingPicture) return;
heightUpdate.setEnabled(checkedId == R.id.heightCustom);
heightUpdate.setAlpha(checkedId == R.id.heightCustom ? 1f : 0.3f);
height.clearFocus();
height.setEnabled(checkedId == R.id.heightCustom);
height.setAlpha(checkedId == R.id.heightCustom ? 1f : 0.5f);
updateCamera(false, true);
}
};
private void updateCamera(boolean updateWidth, boolean updateHeight) {
if (mCapturingPicture) return;
ViewGroup.LayoutParams cameraLayoutParams = camera.getLayoutParams();
int width = cameraLayoutParams.width;
int height = cameraLayoutParams.height;
if (updateWidth) {
switch (widthModeRadioGroup.getCheckedRadioButtonId()) {
case R.id.widthCustom:
String widthInput = this.width.getText().toString();
try { width = Integer.valueOf(widthInput); } catch (Exception e) {}
break;
case R.id.widthWrapContent:
width = ViewGroup.LayoutParams.WRAP_CONTENT;
break;
case R.id.widthMatchParent:
width = ViewGroup.LayoutParams.MATCH_PARENT;
break;
}
}
if (updateHeight) {
switch (heightModeRadioGroup.getCheckedRadioButtonId()) {
case R.id.heightCustom:
String heightInput = this.height.getText().toString();
try { height = Integer.valueOf(heightInput); } catch (Exception e) {}
break;
case R.id.heightWrapContent:
height = ViewGroup.LayoutParams.WRAP_CONTENT;
break;
case R.id.heightMatchParent:
// We are in a vertically scrolling container, match parent would not work at all.
height = parent.getHeight();
break;
}
}
cameraLayoutParams.width = width;
cameraLayoutParams.height = height;
camera.addOnLayoutChangeListener(this);
camera.setLayoutParams(cameraLayoutParams);
String what = (updateWidth && updateHeight ? "Width and height" : updateWidth ? "Width" : "Height");
message(what + " updated! Internal preview size: " + camera.getPreviewSize(), false);
}
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
int mCameraWidth = right - left;
int mCameraHeight = bottom - top;
width.setText(String.valueOf(mCameraWidth));
height.setText(String.valueOf(mCameraHeight));
camera.removeOnLayoutChangeListener(this);
}
}

@ -0,0 +1,50 @@
package com.otaliastudios.cameraview.demo;
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import com.otaliastudios.cameraview.CameraView;
import java.util.ArrayList;
public class MessageView extends LinearLayout {
private TextView message;
private TextView title;
public MessageView(Context context) {
this(context, null);
}
public MessageView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public MessageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setOrientation(VERTICAL);
inflate(context, R.layout.control_view, this);
ViewGroup content = findViewById(R.id.content);
inflate(context, R.layout.spinner_text, content);
title = findViewById(R.id.title);
message = (TextView) content.getChildAt(0);
}
public void setTitle(String title) {
this.title.setText(title);
}
public void setMessage(String message) {
this.message.setText(message);
}
}

@ -12,26 +12,9 @@ import com.otaliastudios.cameraview.CameraUtils;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import butterknife.BindView;
import butterknife.ButterKnife;
public class PicturePreviewActivity extends Activity { public class PicturePreviewActivity extends Activity {
@BindView(R.id.image)
ImageView imageView;
@BindView(R.id.nativeCaptureResolution)
TextView nativeCaptureResolution;
@BindView(R.id.actualResolution)
TextView actualResolution;
@BindView(R.id.approxUncompressedSize)
TextView approxUncompressedSize;
@BindView(R.id.captureLatency)
TextView captureLatency;
private static WeakReference<byte[]> image; private static WeakReference<byte[]> image;
public static void setImage(@Nullable byte[] im) { public static void setImage(@Nullable byte[] im) {
@ -42,7 +25,11 @@ public class PicturePreviewActivity extends Activity {
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_picture_preview); setContentView(R.layout.activity_picture_preview);
ButterKnife.bind(this); final ImageView imageView = findViewById(R.id.image);
final MessageView nativeCaptureResolution = findViewById(R.id.nativeCaptureResolution);
final MessageView actualResolution = findViewById(R.id.actualResolution);
final MessageView approxUncompressedSize = findViewById(R.id.approxUncompressedSize);
final MessageView captureLatency = findViewById(R.id.captureLatency);
final long delay = getIntent().getLongExtra("delay", 0); final long delay = getIntent().getLongExtra("delay", 0);
final int nativeWidth = getIntent().getIntExtra("nativeWidth", 0); final int nativeWidth = getIntent().getIntExtra("nativeWidth", 0);
@ -57,14 +44,21 @@ public class PicturePreviewActivity extends Activity {
@Override @Override
public void onBitmapReady(Bitmap bitmap) { public void onBitmapReady(Bitmap bitmap) {
imageView.setImageBitmap(bitmap); imageView.setImageBitmap(bitmap);
approxUncompressedSize.setText(getApproximateFileMegabytes(bitmap) + "MB");
captureLatency.setText(delay + " milliseconds"); approxUncompressedSize.setTitle("Approx. uncompressed size");
approxUncompressedSize.setMessage(getApproximateFileMegabytes(bitmap) + "MB");
captureLatency.setTitle("Capture latency");
captureLatency.setMessage(delay + " milliseconds");
// ncr and ar might be different when cropOutput is true. // ncr and ar might be different when cropOutput is true.
AspectRatio nativeRatio = AspectRatio.of(nativeWidth, nativeHeight); AspectRatio nativeRatio = AspectRatio.of(nativeWidth, nativeHeight);
AspectRatio finalRatio = AspectRatio.of(bitmap.getWidth(), bitmap.getHeight()); AspectRatio finalRatio = AspectRatio.of(bitmap.getWidth(), bitmap.getHeight());
nativeCaptureResolution.setText(nativeWidth + "x" + nativeHeight + " (" + nativeRatio + ")"); nativeCaptureResolution.setTitle("Native capture resolution");
actualResolution.setText(bitmap.getWidth() + "x" + bitmap.getHeight() + " (" + finalRatio + ")"); nativeCaptureResolution.setMessage(nativeWidth + "x" + nativeHeight + " (" + nativeRatio + ")");
actualResolution.setTitle("Actual resolution");
actualResolution.setMessage(bitmap.getWidth() + "x" + bitmap.getHeight() + " (" + finalRatio + ")");
} }
}); });

@ -5,28 +5,29 @@ import android.media.MediaPlayer;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.MediaController; import android.widget.MediaController;
import android.widget.TextView; import android.widget.TextView;
import android.widget.VideoView; import android.widget.VideoView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class VideoPreviewActivity extends Activity { public class VideoPreviewActivity extends Activity {
@BindView(R.id.video) private VideoView videoView;
VideoView videoView;
@BindView(R.id.actualResolution)
TextView actualResolution;
@Override @Override
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_preview); setContentView(R.layout.activity_video_preview);
ButterKnife.bind(this); videoView = findViewById(R.id.video);
videoView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
playVideo();
}
});
final MessageView actualResolution = findViewById(R.id.actualResolution);
Uri videoUri = getIntent().getParcelableExtra("video"); Uri videoUri = getIntent().getParcelableExtra("video");
MediaController controller = new MediaController(this); MediaController controller = new MediaController(this);
@ -38,7 +39,8 @@ public class VideoPreviewActivity extends Activity {
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override @Override
public void onPrepared(MediaPlayer mp) { public void onPrepared(MediaPlayer mp) {
actualResolution.setText(mp.getVideoWidth() + " x " + mp.getVideoHeight()); actualResolution.setTitle("Actual resolution");
actualResolution.setMessage(mp.getVideoWidth() + " x " + mp.getVideoHeight());
ViewGroup.LayoutParams lp = videoView.getLayoutParams(); ViewGroup.LayoutParams lp = videoView.getLayoutParams();
float videoWidth = mp.getVideoWidth(); float videoWidth = mp.getVideoWidth();
float videoHeight = mp.getVideoHeight(); float videoHeight = mp.getVideoHeight();
@ -50,8 +52,6 @@ public class VideoPreviewActivity extends Activity {
}); });
} }
@OnClick(R.id.video)
void playVideo() { void playVideo() {
if (videoView.isPlaying()) return; if (videoView.isPlaying()) return;
videoView.start(); videoView.start();

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"> <shape
xmlns:android="http://schemas.android.com/apk/res/android"
<solid android:color="@color/colorPrimary"/> android:shape="oval">
<corners android:radius="4dp"/> <solid android:color="@color/colorAccent"/>
</shape> </shape>

@ -5,5 +5,5 @@
android:viewportHeight="24.0"> android:viewportHeight="24.0">
<path <path
android:fillColor="#FFFFFFFF" android:fillColor="#FFFFFFFF"
android:pathData="M7,2v11h3v9l7,-12h-4l4,-8z"/> android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
</vector> </vector>

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/root"
android:background="#FF444444"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Camera -->
<com.otaliastudios.cameraview.CameraView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/camera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:keepScreenOn="true"
app:cameraGrid="off"
app:cameraCropOutput="false"
app:cameraFacing="back"
app:cameraFlash="off"
app:cameraAudio="on"
app:cameraGestureTap="focusWithMarker"
app:cameraGestureLongTap="none"
app:cameraGesturePinch="zoom"
app:cameraGestureScrollHorizontal="exposureCorrection"
app:cameraGestureScrollVertical="none"
app:cameraJpegQuality="100"
app:cameraSessionType="picture" />
<!-- Controls -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:padding="16dp"
android:orientation="horizontal"
android:weightSum="3">
<ImageButton
android:id="@+id/edit"
android:layout_width="56dp"
android:layout_height="56dp"
android:background="@drawable/background"
app:srcCompat="@drawable/ic_edit" />
<Space
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" />
<ImageButton
android:id="@+id/capturePhoto"
android:layout_width="56dp"
android:layout_height="56dp"
android:background="@drawable/background"
app:srcCompat="@drawable/ic_photo" />
<Space
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" />
<ImageButton
android:id="@+id/captureVideo"
android:layout_width="56dp"
android:layout_height="56dp"
android:background="@drawable/background"
app:srcCompat="@drawable/ic_video" />
<Space
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" />
<ImageButton
android:id="@+id/toggleCamera"
android:layout_width="56dp"
android:layout_height="56dp"
android:background="@drawable/background"
app:srcCompat="@drawable/ic_switch" />
</LinearLayout>
<!-- Edit -->
<android.support.v4.widget.NestedScrollView
android:id="@+id/controls"
android:background="@android:color/white"
app:layout_behavior="@string/bottom_sheet_behavior"
app:behavior_hideable="true"
app:behavior_peekHeight="300dp"
app:behavior_skipCollapsed="false"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>

@ -1,555 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:descendantFocusability="beforeDescendants"
android:focusable="true"
android:focusableInTouchMode="true">
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- Camera -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.otaliastudios.cameraview.CameraView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/camera"
android:layout_width="match_parent"
android:layout_height="400dp"
android:layout_gravity="center_horizontal"
android:keepScreenOn="true"
app:cameraGrid="off"
app:cameraCropOutput="false"
app:cameraFacing="back"
app:cameraFlash="off"
app:cameraAudio="on"
app:cameraGestureTap="focusWithMarker"
app:cameraGestureLongTap="none"
app:cameraGesturePinch="zoom"
app:cameraGestureScrollHorizontal="exposureCorrection"
app:cameraGestureScrollVertical="none"
app:cameraJpegQuality="100"
app:cameraSessionType="picture" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- Controls -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="4">
<ImageButton
android:id="@+id/capturePhoto"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight="1"
android:padding="8dp"
android:background="@drawable/background"
app:srcCompat="@drawable/ic_photo" />
<ImageButton
android:id="@+id/captureVideo"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight="1"
android:padding="8dp"
android:background="@drawable/background"
app:srcCompat="@drawable/ic_video" />
<ImageButton
android:id="@+id/toggleFlash"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight="1"
android:padding="8dp"
android:background="@drawable/background"
app:srcCompat="@drawable/ic_flash" />
<ImageButton
android:id="@+id/toggleCamera"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight="1"
android:padding="8dp"
android:background="@drawable/background"
app:srcCompat="@drawable/ic_switch" />
</LinearLayout>
<!-- Session type -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<View
android:layout_width="2.5dp"
android:layout_height="match_parent"
android:background="@color/colorPrimary" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:text="SESSION TYPE"
android:textColor="@android:color/black"
android:textSize="14sp"
android:textStyle="bold" />
<RadioGroup
android:id="@+id/sessionTypeRadioGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:checkedButton="@+id/sessionTypePicture"
android:orientation="horizontal">
<RadioButton
android:id="@+id/sessionTypePicture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Picture" />
<RadioButton
android:id="@+id/sessionTypeVideo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="Video" />
</RadioGroup>
</LinearLayout>
</FrameLayout>
<!-- Crop output -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<View
android:layout_width="2.5dp"
android:layout_height="match_parent"
android:background="@color/colorPrimary" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:text="CROP OUTPUT"
android:textColor="@android:color/black"
android:textSize="14sp"
android:textStyle="bold" />
<RadioGroup
android:id="@+id/cropModeRadioGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:checkedButton="@+id/modeCropFullSize"
android:orientation="horizontal">
<RadioButton
android:id="@+id/modeCropFullSize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Off" />
<RadioButton
android:id="@+id/modeCropVisible"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="On" />
</RadioGroup>
</LinearLayout>
</FrameLayout>
<!-- Width -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<View
android:layout_width="2.5dp"
android:layout_height="match_parent"
android:background="@color/colorPrimary" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:descendantFocusability="beforeDescendants"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:text="WIDTH"
android:textColor="@android:color/black"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:id="@+id/screenWidth"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:text="screen: 1080px"
android:textColor="@android:color/black"
android:textSize="11sp" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.otaliastudios.cameraview.demo.AutoUnfocusEditText
android:id="@+id/width"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="120dp"
android:hint="pixels"
android:inputType="number" />
<Button
android:id="@+id/widthUpdate"
android:layout_width="90dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical|right"
android:layout_marginRight="15dp"
android:background="@drawable/background"
android:gravity="center"
android:text="UPDATE"
android:stateListAnimator="@null"
android:textColor="@android:color/white"
android:textSize="14sp"
android:textStyle="bold" />
</FrameLayout>
<RadioGroup
android:id="@+id/widthModeRadioGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:checkedButton="@+id/widthCustom"
android:orientation="horizontal">
<RadioButton
android:id="@+id/widthCustom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Custom" />
<RadioButton
android:id="@+id/widthWrapContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="wrap_content" />
<RadioButton
android:id="@+id/widthMatchParent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="match_parent" />
</RadioGroup>
</LinearLayout>
</FrameLayout>
<!-- Height -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<View
android:layout_width="2.5dp"
android:layout_height="match_parent"
android:background="@color/colorPrimary" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:descendantFocusability="beforeDescendants"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:text="HEIGHT"
android:textColor="@android:color/black"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:id="@+id/screenHeight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:text="screen: 1920px"
android:textColor="@android:color/black"
android:textSize="11sp" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.otaliastudios.cameraview.demo.AutoUnfocusEditText
android:id="@+id/height"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="120dp"
android:hint="pixels"
android:inputType="number" />
<Button
android:id="@+id/heightUpdate"
android:layout_width="90dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical|right"
android:layout_marginRight="15dp"
android:background="@drawable/background"
android:gravity="center"
android:text="UPDATE"
android:stateListAnimator="@null"
android:textColor="@android:color/white"
android:textSize="14sp"
android:textStyle="bold" />
</FrameLayout>
<RadioGroup
android:id="@+id/heightModeRadioGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:checkedButton="@+id/heightCustom"
android:orientation="horizontal">
<RadioButton
android:id="@+id/heightCustom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Custom" />
<RadioButton
android:id="@+id/heightWrapContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="wrap_content" />
<RadioButton
android:id="@+id/heightMatchParent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="match_parent" />
</RadioGroup>
</LinearLayout>
</FrameLayout>
<!-- Video Quality -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<View
android:layout_width="2.5dp"
android:layout_height="match_parent"
android:background="@color/colorPrimary" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:text="VIDEO QUALITY"
android:textColor="@android:color/black"
android:textSize="14sp"
android:textStyle="bold" />
<HorizontalScrollView
android:layout_marginTop="4dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RadioGroup
android:id="@+id/videoQualityRadioGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checkedButton="@+id/videoQuality480p"
android:orientation="horizontal">
<RadioButton
android:id="@+id/videoQualityLowest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="low" />
<RadioButton
android:id="@+id/videoQualityQvga"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="QVGA" />
<RadioButton
android:id="@+id/videoQuality480p"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="480p" />
<RadioButton
android:id="@+id/videoQuality720p"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="720p" />
<RadioButton
android:id="@+id/videoQuality1080p"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1080p" />
<RadioButton
android:id="@+id/videoQuality2160p"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2160p" />
<RadioButton
android:id="@+id/videoQualityHighest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="high" />
</RadioGroup>
</HorizontalScrollView>
</LinearLayout>
</FrameLayout>
<!-- Grid -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<View
android:layout_width="2.5dp"
android:layout_height="match_parent"
android:background="@color/colorPrimary" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:text="GRID MODE"
android:textColor="@android:color/black"
android:textSize="14sp"
android:textStyle="bold" />
<RadioGroup
android:id="@+id/gridModeRadioGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:checkedButton="@+id/gridModeOff"
android:orientation="horizontal">
<RadioButton
android:id="@+id/gridModeOff"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Off" />
<RadioButton
android:id="@+id/gridMode3x3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="3X3" />
<RadioButton
android:id="@+id/gridMode4x4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="4x4" />
<RadioButton
android:id="@+id/gridModeGolden"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="Golden ratio" />
</RadioGroup>
</LinearLayout>
</FrameLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>

@ -3,16 +3,11 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@android:color/white"> android:background="@android:color/white">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView <ImageView
android:id="@+id/image" android:id="@+id/image"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -20,163 +15,25 @@
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:adjustViewBounds="true" /> android:adjustViewBounds="true" />
</FrameLayout> <com.otaliastudios.cameraview.demo.MessageView
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<View
android:layout_width="2.5dp"
android:layout_height="match_parent"
android:background="@color/colorPrimary" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:text="NATIVE CAPTURE RESOLUTION"
android:textColor="@android:color/black"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/nativeCaptureResolution" android:id="@+id/nativeCaptureResolution"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:textColor="@android:color/black"
android:textSize="14.5sp" />
</LinearLayout>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp">
<View
android:layout_width="2.5dp"
android:layout_height="match_parent"
android:background="@color/colorPrimary" />
<LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"/>
android:layout_marginLeft="10dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:text="ACTUAL RESOLUTION"
android:textColor="@android:color/black"
android:textSize="18sp"
android:textStyle="bold" />
<TextView <com.otaliastudios.cameraview.demo.MessageView
android:id="@+id/actualResolution" android:id="@+id/actualResolution"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:textColor="@android:color/black"
android:textSize="14.5sp" />
</LinearLayout>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp">
<View
android:layout_width="2.5dp"
android:layout_height="match_parent"
android:background="@color/colorPrimary" />
<LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"/>
android:layout_marginLeft="10dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:text="APPROX. UNCOMPRESSED SIZE"
android:textColor="@android:color/black"
android:textSize="18sp"
android:textStyle="bold" />
<TextView <com.otaliastudios.cameraview.demo.MessageView
android:id="@+id/approxUncompressedSize" android:id="@+id/approxUncompressedSize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:textColor="@android:color/black"
android:textSize="14.5dp" />
</LinearLayout>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"/>
android:layout_marginTop="24dp">
<View
android:layout_width="2.5dp"
android:layout_height="match_parent"
android:background="@color/colorPrimary" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:orientation="vertical">
<TextView <com.otaliastudios.cameraview.demo.MessageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:text="CAPTURE LATENCY"
android:textColor="@android:color/black"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/captureLatency" android:id="@+id/captureLatency"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"/>
android:layout_marginLeft="3dp"
android:textColor="@android:color/black"
android:textSize="14.5sp" />
</LinearLayout>
</FrameLayout>
</LinearLayout>
</LinearLayout> </LinearLayout>

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" <ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@android:color/white"> android:background="@android:color/white">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -14,45 +14,10 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="200dp"/> android:layout_height="200dp"/>
<LinearLayout <com.otaliastudios.cameraview.demo.MessageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- Resolution -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<View
android:layout_width="2.5dp"
android:layout_height="match_parent"
android:background="@color/colorPrimary" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:text="ACTUAL RESOLUTION"
android:textColor="@android:color/black"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/actualResolution" android:id="@+id/actualResolution"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"/>
android:layout_marginLeft="3dp"
android:textColor="@android:color/black"
android:textSize="14.5sp" />
</LinearLayout>
</FrameLayout>
</LinearLayout>
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<merge
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
style="@style/TextAppearance.AppCompat.Subhead"
android:id="@+id/title"
android:layout_marginTop="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<FrameLayout
android:id="@+id/content"
android:paddingTop="4dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<View
android:id="@+id/divider"
android:layout_marginTop="8dp"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#44AAAAAA" />
</merge>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/TextAppearance.AppCompat.Medium"
android:padding="12dp"
android:textColor="@android:color/black"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

@ -2,5 +2,5 @@
<resources> <resources>
<color name="colorPrimary">#009966</color> <color name="colorPrimary">#009966</color>
<color name="colorPrimaryDark">#00734d</color> <color name="colorPrimaryDark">#00734d</color>
<color name="colorAccent">#65FF2D</color> <color name="colorAccent">#57db27</color>
</resources> </resources>

@ -8,11 +8,7 @@
<item name="colorAccent">@color/colorAccent</item> <item name="colorAccent">@color/colorAccent</item>
</style> </style>
<style name="Theme.MainActivity" parent="AppTheme"> <style name="Theme.MainActivity" parent="AppTheme"/>
</style> <style name="Theme.PreviewActivity" parent="Theme.AppCompat.NoActionBar"/>
<style name="Theme.PreviewActivity" parent="Theme.AppCompat.NoActionBar">
</style>
</resources> </resources>

Loading…
Cancel
Save