Hi I have a floating window in which my floating window serves as the video and it also have a controls inside the video which under the floating window
Now my question is it possible that I can rotate my custom view from floating window only without affecting the orientation of my activity
If someone already tried it please guide me towards it.
Thank you.
I have never done it before. But I have an idea. You can use the below code to get the current orientation of the screen on your device.
OrientationEventListener onrientationEventListener = new OrientationEventListener(context, SensorManager.SENSOR_DELAY_UI) {
#Override
public void onOrientationChanged(int rotation) {
Logger.e("Orientation: " + rotation);
}
};
And after that, depends on the value of "rotation", you can use rotate animation in Android to rotate your custom view.
#Beginer: Here is the code I implemented it. I used the above code in my custom view in my small camera app. It helps me to know which degree should I rotate the bitmap after taken. The toScreenOrientation() method bellow return a value in degrees (0, 90, 180, 270) you also modify it by yourself(whatever you want).
Using setOrientationChangedListener() method to help the parent(Activity, Fragment, etc.) receives a callback also.
public class TakePhotoView extends ConstraintLayout {
private static final int SCREEN_ORIENTATION_0 = 0;
private static final int SCREEN_ORIENTATION_90 = 90;
private static final int SCREEN_ORIENTATION_180 = 180;
private static final int SCREEN_ORIENTATION_270 = 270;
private OnOrientationChangedListener mOnOrientationChangedListener;
private OrientationEventListener mOrientationEventListener;
private int mScreenRotation;
public TakePhotoView(Context context) {
this(context, null);
}
public TakePhotoView(Context context, AttributeSet attrs) {
super(context, attrs);
//....do something here
mOrientationEventListener = new OrientationEventListener(context, SensorManager.SENSOR_DELAY_UI) {
#Override
public void onOrientationChanged(int rotation) {
Logger.e("Orientation: " + rotation);
if (rotation == OrientationEventListener.ORIENTATION_UNKNOWN) {
mScreenRotation = DEFAULT_SCREEN_ROTATION;
return;
}
mScreenRotation = rotation;
if(mOnOrientationChangedListener != null){
mOnOrientationChangedListener.onOrientationChanged(rotation);
}
}
};
}
private void takePhoto(Camera camera) {
if (camera != null) {
camera.takePicture(null, null, mPictureCallback);
}
}
private Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
final int screenRotation = mScreenRotation;
int rotate = toScreenOrientation(screenRotation);
// Rotate/Flip the bitmap depends on the 'rotate' value
}
};
/**
* Converts sensor rotation in degrees to screen orientation constants.
*
* #param rotation sensor rotation angle in degrees
* #return Screen orientation angle in degrees (0, 90, 180, 270).
*/
private int toScreenOrientation(int rotation) {
if (rotation > 290 || rotation <= 70) {
return SCREEN_ORIENTATION_0;
} else if (rotation > 70 && rotation <= 110) {
return SCREEN_ORIENTATION_90;
} else if (rotation > 110 && rotation <= 250) {
return SCREEN_ORIENTATION_180;
} else {
return SCREEN_ORIENTATION_270;
}
}
public void setOrientationChangedListener(OnOrientationChangedListener orientationChangedListener){
this.mOnOrientationChangedListener = orientationChangedListener;
}
////////////////////////////////////////////////////////////////////////////////////////////////
// Interfaces
////////////////////////////////////////////////////////////////////////////////////////////////
public interface OnOrientationChangedListener {
void onOrientationChanged(int rotation);
}
}
Can I use this listener even I disable rotation in my manifest?
-> It still works fine.
Hope it helps.
Looks like you do not want your Activity to be recreated on device rotation.
If so, then add configChanges attribute in AndroidManifest:
<activity
...
android:configChanges="orientation" >
This will stop activity recreation on rotation. But in your activity you can check that device has been rotated in onConfigurationChanged() method:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
...
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
...
}
}
Do not forget to read android developer guides. ;)
I have found a way to do this but I used alertDailog. The logic will be the same for all views.
AlertDialog dialog;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.stack_overflow2);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
AlertDialog.Builder alert123 = new AlertDialog.Builder(StackOverflow2.this);
View current_view = getLayoutInflater().inflate(R.layout.password_alert,null);
l2 = current_view.findViewById(R.id.linearView);
// Here l2 is linear layout getting root layout of password_alert
alert123.setView(current_view);
dialog = alert123.create();
dialog.show();
OrientationEventListener onrientationEventListener = new OrientationEventListener(getBaseContext(), SensorManager.SENSOR_DELAY_UI) {
#Override
public void onOrientationChanged(int rotation) {
Log.e("Orientation: " , String.valueOf(rotation));
if(rotation==270 || rotation==90)
{
if(rotation==270)
{
l2.setRotation(90);
}
else
{
l2.setRotation(270);
}
dialog.getWindow().setLayout(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
Toast.makeText(StackOverflow2.this, "Change Dialog Rotation", Toast.LENGTH_SHORT).show();
}
else
{
if(rotation==180)
{
l2.setRotation(180);
}
else
{
l2.setRotation(0);
}
Toast.makeText(StackOverflow2.this, "Normal Display to Occur", Toast.LENGTH_SHORT).show();
}
}
};
if (onrientationEventListener.canDetectOrientation()) {
Log.v("ORIE", "Can detect orientation");
onrientationEventListener.enable();
} else {
Log.v("ORIE", "Cannot detect orientation");
onrientationEventListener.disable();
}
}
Here are some pictures :
0 Degree
90 Degree
270 Degree
As you can see the background activity is in potrait mode always. The alert dialog's height and width is a little off but you can change your view's dimensions differently. I hope this code solves your problem.
Related
I have come across a problem where the orientation sensorPortrait does not work, i have tried enabling both through the manifest and within the activity itself with
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
But this seems to just be locked in normal portrait mode, however if i try `fullSensor'
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
which according to the docs
The orientation is determined by the device orientation sensor for any of the 4 orientations. This is similar to "sensor" except this allows any of the 4 possible screen orientations, regardless of what the device will normally do (for example, some devices won't normally use reverse portrait or reverse landscape, but this enables those). Added in API level 9.
and it does exactly that, all 4 orientations are possible. If i also try
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
I am able to achieve reverse portrait, which leads me back to my original question, why does sensorPortrait not work? It looks like it has something to do with this line from the docs for `fullSensor'
regardless of what the device will normally do (for example, some devices won't normally use reverse portrait or reverse landscape, but this enables those)
So how do i enable it, is that possible and why does fullSensor seem to override it but not sensorPortrait? I can't seem to find any mention of how to do so. This question suggests that the PhoneWindowManager is responsible for this.
Is the ideal solution just to create an OrientationEventListener() and manually call setRequestedOrientation() manually depending on the values returned via onOrientationChanged(int orientation)?
As a work around i have created a SensorPortraitActivity:
public class SensorPortraitActivity extends AppCompatActivity {
private static final int PORTRAIT = 0;
private static final int REVERSE_PORTRAIT = 180;
private static final int OFFSET = 45;
private static final int UNKNOWN = -1;
// account for 0 = 360 (eg. -1 = 359)
private static final int PORTRAIT_START = PORTRAIT - OFFSET + 360;
private static final int PORTRAIT_END = PORTRAIT + OFFSET;
private static final int REVERSE_PORTRAIT_START = REVERSE_PORTRAIT - OFFSET;
private static final int REVERSE_PORTRAIT_END = REVERSE_PORTRAIT + OFFSET;
private OrientationChangeListener mListener;
private OrientationEventListener mOrientationListener;
private CurrentOrientation mCurrentOrientation;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mOrientationListener = new OrientationEventListener(this) {
#Override
public void onOrientationChanged(int i) {
orientationChanged(i);
}
};
}
#Override
protected void onResume() {
super.onResume();
mOrientationListener.enable();
}
#Override
protected void onPause() {
super.onPause();
mOrientationListener.disable();
}
//optional
public void setOrientationChangeListener(OrientationChangeListener listener){
mListener = listener;
}
private void orientationChanged(int degrees) {
if (degrees != UNKNOWN){
if (degrees >= PORTRAIT_START || degrees <= PORTRAIT_END){
if (mCurrentOrientation != CurrentOrientation.PORTRAIT){
mCurrentOrientation = CurrentOrientation.PORTRAIT;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
if (mListener != null){
mListener.onPortrait();
}
}
} else if (degrees >= REVERSE_PORTRAIT_START && degrees <= REVERSE_PORTRAIT_END){
if (mCurrentOrientation != CurrentOrientation.REVERSE_PORTRAIT){
mCurrentOrientation = CurrentOrientation.REVERSE_PORTRAIT;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
if (mListener != null) {
mListener.onReversePortrait();
}
}
}
}
}
interface OrientationChangeListener {
void onPortrait();
void onReversePortrait();
}
enum CurrentOrientation {
PORTRAIT, REVERSE_PORTRAIT
}
}
Although it does seem like overkill for something as simple as this.
To use it simple extend SensorPortraitActivity
public class ExampleActivity extends SensorPortraitActivity implements SensorPortraitView.OrientationChangeListener {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set listener if you want callbacks
super.setOrientationChangeListener(this);
}
#Override
public void onPortrait() {
//portrait orientation
}
#Override
public void onReversePortrait() {
//reverse portrait orientation
}
}
I'm trying to create two camera previews in the same fragment layout, but I've encountered some strange issues, like:
the preview freezes and the camera preview isn't changed,
sometimes camera doesn't start at all.
Here is my custom SurfaceView for the Camera:
#SuppressWarnings("deprecation")
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "CameraPreview";
private SurfaceHolder mHolder;
private Camera mCamera;
private List<Camera.Size> mSupportedPreviewSizes;
private Camera.Size mPreviewSize;
private int currentVolume;
private boolean isVolumeChanged = false;
public CameraPreview(Context context, Camera mCamera) {
super(context);
setCamera(mCamera);
init();
}
public CameraPreview(Context context) {
super(context);
}
public CameraPreview(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CameraPreview(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public CameraPreview(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
/**
* Initialize the SurfaceView which will be used to display the camera preview.
* <p/>
* Only an general setup for the SurfaceView should be done in this method.
*/
private void init() {
setDrawingCacheEnabled(true);
}
/**
* Set the camera to the SurfaceView.
*
* #param camera
* The camera object which will be set to the SurfaceView.
*/
public void setCamera(Camera camera) {
mCamera = camera;
// supported preview sizes
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// empty. surfaceChanged will take care of stuff
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
LogUtils.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or reformatting changes here
try {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
// set the orientation of the pictures taken
//TODO: match this orientation value with the one used for display
parameters.setRotation(90);
// set the focus mode
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
mCamera.setParameters(parameters);
} catch (RuntimeException e) {
// This could happen when concurrency of the camera is happening (especially in dual shot mode)
//TODO: optimize the camera flow to avoid this issue
LogUtils.d(TAG, "Error setting camera parameters: " + e.getMessage());
}
// Force the orientation in Portrait mode
// TODO: get the orientation from the device
mCamera.setDisplayOrientation(90);
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (IOException e) {
LogUtils.e(TAG, "Error starting camera preview: " + e.getMessage());
}
}
/**
* Disable the default shutter sound when taking a picture.
*/
private void disableShutterSound() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
boolean shutterState = mCamera.enableShutterSound(false);
LogUtils.i(TAG, "Shutter sound was" + (!shutterState ? "not " : " ") + "disabled");
} else {
LogUtils.i(TAG, "Trying to disable shutter sound by altering the system audio manager.");
// Backward compatibility method for disabling the shutter sound
AudioManager audio = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
currentVolume = audio.getStreamVolume(AudioManager.STREAM_SYSTEM);
audio.setStreamVolume(AudioManager.STREAM_SYSTEM, 0, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
MediaPlayer media = MediaPlayer.create(getContext(), R.raw.camera_shutter_click);
media.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
isVolumeChanged = true;
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mCamera != null) {
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
float ratio;
if (mPreviewSize.height >= mPreviewSize.width) {
ratio = (float) mPreviewSize.height / (float) mPreviewSize.width;
} else {
ratio = (float) mPreviewSize.width / (float) mPreviewSize.height;
}
// One of these methods should be used, second method squishes preview slightly
// setMeasuredDimension(width, width);
setMeasuredDimension(width, (int) (width * ratio));
// setMeasuredDimension((int) (width * ratio), height);
} else {
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
}
}
private 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.height / size.width;
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 void releaseCamera() {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.release();
mCamera = null;
}
}
/**
* Check if the Camera object was passed and set to the SurfaceView.
*
* #return {#code true} if the Camera object is valid, {#code false} otherwise
*/
public boolean isCameraSet() {
return null != mCamera;
}
public void takePicture() {
if (null != mCamera) {
// Disable the shutter sound when taking an picture
disableShutterSound();
mCamera.takePicture(shutterCallback, rawCallback, postViewCallback, jpegCallback);
}
}
private void resetCam() {
if (null != mCamera) {
mCamera.startPreview();
setCamera(mCamera);
}
}
/**
* The shutter callback occurs after the image is captured
*/
private Camera.ShutterCallback shutterCallback = new Camera.ShutterCallback() {
public void onShutter() {
MediaPlayer.create(getContext(), R.raw.camera_shutter_click).start();
LogUtils.d(TAG, "onShutter");
}
};
/**
* The raw callback occurs when the raw image data is available.<br/>(<b>NOTE:</b> the data will be null if there is
* no raw image callback buffer available or the raw image callback buffer is not large enough to hold the raw
* image).
*/
private Camera.PictureCallback rawCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
LogUtils.d(TAG, "onPictureTaken - raw");
}
};
/**
* The jpeg callback occurs when the compressed image is available.
*/
private Camera.PictureCallback jpegCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
if (isVolumeChanged) {
// Reset the audio settings which where set before trying to take an picture
AudioManager audio = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
audio.setStreamVolume(AudioManager.STREAM_SYSTEM, currentVolume,
AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
// reset flag for volume control
isVolumeChanged = false;
}
new CameraSavePicture().execute(data);
resetCam();
LogUtils.d(TAG, "onPictureTaken - jpeg");
}
};
/**
* The postview callback occurs when a scaled, fully processed postview image is available. <br/> (<b>NOTE:</b> not
* all hardware supports this)
*/
private Camera.PictureCallback postViewCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
LogUtils.d(TAG, "onPictureTaken - postview");
}
};
}
This is the relevant part of the layout for the fragment:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/black">
<FrameLayout
android:id="#+id/full_camera_preview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<FrameLayout
android:id="#+id/small_camera_preview"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
/>
</RelativeLayout>
And this is the Camera fragment:
public class CameraFragment extends Fragment implements View.OnClickListener, EventBusInterface {
private static final String TAG = "Camera Fragment";
private ImageButton flipCameraButton;
private Button takePicture;
private RelativeLayout content;
private RelativeLayout controlPanel;
private CameraPreview fullCameraPreview;
private FrameLayout fullCameraLayout;
private CameraPreview smallCameraPreview;
private FrameLayout smallCameraLayout;
/**
* The mode of the camera which shoul initially be displayed.
*/
private CameraMode currentCameraMode = CameraMode.BACK;
/**
* Do not use to instantiate a fragment. Use newInstance method instead.
*/
public CameraFragment() {
}
/**
* Use this method to get a new instance of the fragment, and give eventually add parameters if you need to pass
* data to it and retrieve it in onCreate using getArguments.
*
* #return a new instance of the current fragment.
*/
public static CameraFragment newInstance() {
final CameraFragment cameraFragment = new CameraFragment();
Bundle arguments = new Bundle();
cameraFragment.setArguments(arguments);
return cameraFragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get the argument passed on the custom initialization of the fragment
Bundle arguments = getArguments();
if (null != savedInstanceState) {
// Get the last camera mode set by the user
CameraMode savedCameraMode = (CameraMode) savedInstanceState.getSerializable("CAMERA_MODE");
if (null != savedCameraMode) {
currentCameraMode = savedCameraMode;
}
}
// setRetainInstance(true); //Will ignore onDestroy Method (Nested Fragments no need this if parent
// have it)
}
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putSerializable("CAMERA_MODE", currentCameraMode);
super.onSaveInstanceState(outState);
}
#Override
public void onViewStateRestored(Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_timeline_camera, container, false);
// BUG FIX: To avoid the window background overlapping this fragment we set it's background to transparent so
// that when the fragment is moved(scrolled) it will still be visible
this.getActivity().getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
initViews(view);
setListeners();
// Setup the camera mode which will initially be displayed.
setUpCameraMode(currentCameraMode);
return view;
}
#Override
public void onResume() {
super.onResume();
}
#SuppressWarnings("deprecation")
private void setUpCameraMode(final CameraMode cameraMode) {
// The front camera SurfaceView will need to be changed, release it first
releaseSmallCamera();
// The full SurfaceView has to be changed because the camera mode will be changed from Back to Front or
// Front to Back
releaseFullCamera();
resizeFullCamera(cameraMode == CameraMode.DUAL);
switch (cameraMode) {
case BACK:
setupFullCamera(CameraInfo.CAMERA_FACING_BACK);
break;
case FRONT:
setupFullCamera(CameraInfo.CAMERA_FACING_FRONT);
break;
case DUAL:
setUpDualCamera();
break;
}
}
#Override
public void onStart() {
super.onStart();
if (!EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().register(this);
}
// This is required because we need to resume the camera when we get back in the fragment.
if (null != getView()) {
// Setup the camera mode which will initially be displayed.
setUpCameraMode(currentCameraMode);
}
}
#Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
// The front camera SurfaceView will need to be changed, release it first
releaseSmallCamera();
// The full SurfaceView has to be changed because the camera mode will be changed from Back to Front or
// Front to Back
releaseFullCamera();
}
/**
* Initialize the view for the current fragment.
*
* #param view
* The view which was inflated for this fragment.
*/
private void initViews(View view) {
controlPanel = (RelativeLayout) view.findViewById(R.id.control_panel);
fullCameraLayout = (FrameLayout) view.findViewById(R.id.full_camera_preview);
smallCameraLayout = (FrameLayout) view.findViewById(R.id.small_camera_preview);
flipCameraButton = (ImageButton) view.findViewById(R.id.flip_camera_button);
takePicture = (Button) view.findViewById(R.id.camera_take_picture);
}
/**
* Setup the listeners required for this fragment.
*/
private void setListeners() {
flipCameraButton.setOnClickListener(this);
takePicture.setOnClickListener(this);
}
/**
* Sets up the SurfaceView where the Full preview will be display. <br/> The full SurfaceView can show the camera
* that faces the same direction as the screen and the camera tjat faces the opposite direction as the screen.
*
* #param facingOfTheCamera
* The facing of the camera that has to be shown in the Full SurfaceView. <br/>Usually {#link
* CameraInfo#CAMERA_FACING_BACK} or {#link CameraInfo#CAMERA_FACING_FRONT}.<br/> If an invalid value is
* set, the preview for the back camera will be setup.
*/
#SuppressWarnings("deprecation")
private void setupFullCamera(int facingOfTheCamera) {
// Full camera can show the back & front cameras
CameraMode cameraMode;
if (facingOfTheCamera == CameraInfo.CAMERA_FACING_BACK) {
cameraMode = CameraMode.BACK;
} else if (facingOfTheCamera == CameraInfo.CAMERA_FACING_FRONT) {
cameraMode = CameraMode.FRONT;
} else {
// Default to the back camera
cameraMode = CameraMode.BACK;
}
if (null == fullCameraPreview) {
fullCameraPreview = new CameraPreview(getActivity(), CameraUtils.getCamera(cameraMode));
}
if (fullCameraLayout.getVisibility() != View.VISIBLE) {
fullCameraLayout.setVisibility(View.VISIBLE);
}
if (fullCameraLayout.getChildCount() == 0) {
// The View for displaying the Camera preview was not added in the layout, we need to add it now.
fullCameraLayout.addView(fullCameraPreview);
}
}
/**
* Sets up the SurfaceView where the Small preview will be display. <br/> The small SurfaceView will always show the
* camera that faces the same direction as the screen.
*/
private void setupSmallCamera() {
// Small camera always shows the camera that faces the same as the screen
if (null == smallCameraPreview) {
smallCameraPreview = new CameraPreview(getActivity(), CameraUtils.getCamera(CameraMode.FRONT));
}
smallCameraPreview.setZOrderOnTop(true);
// smallCameraPreview.setZOrderMediaOverlay(true);
if (smallCameraLayout.getVisibility() != View.VISIBLE) {
smallCameraLayout.setVisibility(View.VISIBLE);
}
if (smallCameraLayout.getChildCount() == 0) {
// The View for displaying the Camera preview was not added in the layout, we need to add it now.
smallCameraLayout.addView(smallCameraPreview);
}
}
/**
* Setup Full SurfaceView preview (display Back camera) and Small SurfaceView preview (display Front camera).
*/
#SuppressWarnings("deprecation")
private void setUpDualCamera() {
// In dual mode camera preview display, the full preview is showing the back camera & the small preview
// displays the front camera
setupFullCamera(CameraInfo.CAMERA_FACING_BACK);
setupSmallCamera();
}
private void resizeFullCamera(boolean shrink) {
// The dual camera doesn't work if two SurfaceViews overlap - use this to resize the full camera so that it
// is not overlapped by the small camera
RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
if (shrink) {
p.addRule(RelativeLayout.BELOW, R.id.small_camera_preview);
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
p.removeRule(RelativeLayout.BELOW);
} else {
p.addRule(RelativeLayout.BELOW, 0);
}
}
fullCameraLayout.setLayoutParams(p);
}
/**
* Release the Camera Object used for the full camera mode. <br/> Remove the SurfaceView from the layout and
* invalidate it.
*/
private void releaseFullCamera() {
if (null != fullCameraPreview) {
fullCameraPreview.releaseCamera();
}
if (null != fullCameraLayout) {
// Remove the SurfaceView from the layout
fullCameraLayout.removeAllViews();
fullCameraLayout.setVisibility(View.INVISIBLE);
}
// Invalidate the SurfaceView
fullCameraPreview = null;
}
/**
* Release the Camera Object used for the small camera mode. <br/> Remove the SurfaceView from the layout and
* invalidate it.
*/
private void releaseSmallCamera() {
if (null != smallCameraPreview) {
smallCameraPreview.releaseCamera();
}
if (null != smallCameraLayout) {
// Remove the SurfaceView from the layout
smallCameraLayout.removeAllViews();
smallCameraLayout.setVisibility(View.INVISIBLE);
}
// Invalidate the SurfaceView
smallCameraPreview = null;
}
/**
* Flip between the camera modes supported. <br/> The flip is like an infinite carousel.
*/
private void flipCamera() {
// Set up the next mode for the camera preview/s display
setUpCameraMode(currentCameraMode.getNext());
// Update the current mode of the camera preview/s display
currentCameraMode = currentCameraMode.getNext();
}
#Override
public void onClick(View v) {
final int id = v.getId();
switch (id) {
case R.id.flip_camera_button:
// Flip camera to the next mode available.
flipCamera();
break;
case R.id.camera_take_picture:
takePicture();
break;
}
}
private void takePicture() {
switch (currentCameraMode) {
case BACK:
case FRONT:
if (null != fullCameraPreview) {
fullCameraPreview.takePicture();
} else {
ToastModel toastModel = new ToastModel(ToastType.GENERAL, "Please wait for camera warming up!");
new CustomToast(getActivity()).displayToast(toastModel);
}
break;
case DUAL:
ToastModel toastModel = new ToastModel(ToastType.GENERAL, "Dual picture not supported yet!");
new CustomToast(getActivity()).displayToast(toastModel);
break;
}
}
#Override
public void onEvent(Object event) {
}
#Override
public void onEventMainThread(Object event) {
if (event instanceof String) {
ToastModel toastModel = new ToastModel(ToastType.GENERAL, (String) event);
new CustomToast(getActivity()).displayToast(toastModel);
}
}
#Override
public void onEventBackgroundThread(Object event) {
}
#Override
public void onEventAsync(Object event) {
}
}
What could be the issue for this weird behavior?
Currently I'm not trying to show both previews at the same time, but one by one.
LE:
I have updated the logic for how the flip between camera modes is done.
When only the front or back camera are displayed in the full SurfaceView everything works fine. The problem appears when I use both of them (not necessarily both Camera objects at the same time, but both SurfaceViews visible at the same time & simply change from one to another).
I noticed the following errors in the logs:
D/Camera﹕ [seungmin]_open start
D/Camera﹕ [China_security]_before
D/Camera﹕ [China_security]_after
D/Camera﹕ [seungmin]_open End
D/CameraPreview﹕ Error setting camera parameters: getParameters failed (empty parameters)
W/CameraBase﹕ mediaserver's remote binder Camera object died
W/CameraBase﹕ Camera service died!
W/CameraBase﹕ mediaserver's remote binder Camera object died
E/Camera﹕ Error 100
E/Camera﹕ Error 100
LE2:
I have updated my code & optimized the flow.
I have also figured out why the Camera dies - it was because the SurfaceView for the second Camera was placed on top of the first one. Once the SurfaceViews didn't overlap anymore everything started working fine.
My question now is how can I fix this issue? Why is this happening?
PS: Most of the tests where made on LG G2 device which supports dual shot directly.
You may have stumbled upon an Android limitation regarding overlapping SurfaceViews. You can read more about this limitation here.
Don't think of SurfaceViews as classic views, they function more like a placeholder for getting the screen area (position and size) you want to surrender control to a rendering component. Rendering is actually done on a separate window.
As a solution, you can try calling setZOrderOnTop(true) on the SurfaceView you want on top.This is false by default, so the 2 SurfaceViews will not be on the same z anymore - making them work; one drawback is that the one on top will also be on top of any view you have.
If they do end up working, this is not guaranteed to happen on all devices, so I recommend extensive testing on what devices you consider important.
Another thing you can research is to see if you can tap into the Camera feed and see if you can merge the 2 streams and feeding the result to 1 SurfaceView
How to rotate a dialog fragment 90 or 180 degrees if the activity screen orientation is locked?
Activity declared in manifest:
<activity
...
android:screenOritentation="landscape" />
Dialog fragment:
public class MyFragment extends DialogFragment{
// stuff
}
I've rotated the dialog's layout using NineOldAndroid library. It is working as I expected if I rotate to 180 degree, however if I rotate to 90 degree, the layout is not visible entirely.
I am trying to rotate the entire dialog (not only the layout), inclusive buttons, title, everything, but I couldn't figured out how to to that.
Main idea that You can try use some flags of ActivityInfo on methods onStart() and onStop() at DialogFragment.
For example for DialogFragment you can fix some orientation on onStart() method:
#Override
public void onStart()
{
super.onStart();
// lock screen;
DisplayTools.Orientation orientation = DisplayTools.getDisplatOrientation(getActivity());
getActivity().setRequestedOrientation(orientation == DisplayTools.Orientation.LANDSCAPE
? ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
: ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
}
(this use something flags from ActivityInfo)
And restore orientation on onStop() method:
#Override
public void onStop()
{
super.onStop();
// unlock screen;
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
(on your particular case you must use ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE instead ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED at onStop() method)
Where
public class DisplayTools
{
static public Point getDisplaySize(Context context)
{
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
return size;
}
static public Orientation getDisplatOrientation(Activity activity)
{
if (activity != null)
{
int orientation = activity.getResources().getConfiguration().orientation;
if (orientation == Configuration.ORIENTATION_LANDSCAPE)
{
return Orientation.LANDSCAPE;
}
if (orientation == Configuration.ORIENTATION_PORTRAIT)
{
return Orientation.PORTRAIT;
}
if (orientation == Configuration.ORIENTATION_UNDEFINED)
{
return Orientation.UNDEFINED;
}
}
return Orientation.UNKNOWN;
}
public static enum Orientation
{
UNKNOWN(-1),
UNDEFINED(0),
PORTRAIT(1),
LANDSCAPE(2);
private int tag;
Orientation(int i)
{
this.tag = i;
}
}
}
I hope you understand main idea!
The solution is to inflate a specific layout for the dialog by the current orientation. In my app, the activity is locked to landscape, however, if I turn the device to portrait I am showing a specific layout without recreating the activity.
Note: It is not working with an already opened dialog. The dialog is not rotated when the device is rotated. It is rotated only at creation at the dialog.
Your activity:
public class ActivityMain extends Activity
{
private boolean isPortrait = false;
private boolean isFlip = false;
private OrientationEventListener orientationEventListener;
#Override
protected void onCreate(Bundle bundle)
{
// stuff
setUpOrientationListener();
}
// Register device to detected orientation change
private void setUpOrientationListener()
{
orientationEventListener = new OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL)
{
#Override
public void onOrientationChanged(int orientation)
{
// Device is in portrait
if (orientation > 320 || orientation < 45)
{
if (!isPortrait)
onPortraitRotation();
}
else // Device is flipped
if (orientation > 45 && orientation < 145)
{
if (!isFlip)
onFlipRotation();
}
else // Device is in landscape
{
if (isPortrait)
onLandscapeRotation();
}
}
};
// If device is capable for detecting orientation register listener
if (orientationEventListener.canDetectOrientation())
orientationEventListener.enable();
}
private void onPortraitRotation()
{
isPortrait = true;
isFlip = false;
}
private void onFlipRotation()
{
isFlip = true;
isPortrait = false;
}
private void onLandscapeRotation()
{
isPortrait = false;
isFlip = false;
}
// Creates your custom dialog
private void showCustomDialog()
{
MyDialog dialog = new MyDialog(ActivityMain.this, isPortrait, isFlipped);
dialog.show();
}
}
Now we know the orientation of our device, now create the dialog.
NOTE Use DialogFragment with a static constructor: http://developer.android.com/reference/android/app/DialogFragment.html (however, I am using simple Dialog for demonstration)
public class MyDialog extends Dialog
{
private boolean isPortrait;
private boolean isFlipped;
public MyDialog(Context context, boolean isPortrait, boolean isFlipped)
{
super(context);
this.isPortrait = isPortrait;
this.isFlipped = isFlipped;
}
#Override
protected void onCreate(Bundle bundle)
{
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
// Device is in landscape mode
if (!isPortrait && !isFlipped)
setContentView(R.layout.dialog_landscape);
else
if (isPortrait && !isFlipped) // Device is in portrait
setContentView(R.layout.dialog_vertical);
else // Device is flipped
{
setContentView(R.layout.dialog_landscape);
// Rotate the entire root layout
View layout = findViewById(R.id.rlContainer);
ObjectAnimator.ofFloat(layout, "rotation", 180).setDuration(0).start();
}
}
}
For rotation use NindeOldAndroids library.
NOTE: This solution is working for: landscape, portrait and flipped landscape. To show flipped portrait you must calculate the orientation in the orientation detect listener.
NOTE 2: Do not use system buttons! They are attached to the dialog which is attached to the parent (activity) locked orientation. Use layout-built-in button views.
I think cosic's solution is the best, along with this Activity configuration:
android:configChanges="orientation|screenSize"
...then in your Activity you can implement onConfigurationChanged(), and either ignore the change or do something custom.
I have an Android application using LinearLayout as main layout with a SurfaceView filled by camera preview.
In this I inflate another LinearLayout with three Buttons and a custom TextView. I would like the camera preview to stay always in Landscape orientation and the overlay layout changing according to the device orientation.
I tried setting android:screenOrientation="landscape" in the manifest for the activity but then (of course) also the inflated layout stays always fixed, while not setting the android:screenOrientation property also the camera preview rotate, slowing down the app and showing strange form factors of the preview. Here the relevant code for the layout:
private void setupLayout()
{
setContentView(R.layout.main);
getWindow().setFormat(PixelFormat.UNKNOWN);
// Release camera if owned by someone else
if (camera != null)
releaseCamera();
surfaceView = (SurfaceView) findViewById(R.id.camerapreview);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
controlInflater = LayoutInflater.from(getBaseContext());
View viewControl = controlInflater.inflate(R.layout.control, null);
LayoutParams layoutParamsControl = new LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
this.addContentView(viewControl, layoutParamsControl);
buttonGetCollectingData = (Button) findViewById(R.id.getcolldata);
buttonGetCollectingData.setOnClickListener(new Button.OnClickListener()
{
public void onClick(View arg0)
{
...
}
});
btnBackHome = (Button) findViewById(R.id.btnBackHome);
btnBackHome.setOnClickListener(new Button.OnClickListener()
{
public void onClick(View arg0)
{
...
}
});
autoFitTextViewMainMsg = (AutoFitTextView) findViewById(R.id.autoFitTextViewMainMsg);
buttonTakePicture.setOnClickListener(new Button.OnClickListener()
{
public void onClick(View arg0)
{
...
}
});
}
Any idea on how to accomplish this would be really appreciated!
You can make use of custom orientation event listener to get the orientation and set your UI as according.
First, create a class CustomOrientationEventListener
public abstract class CustomOrientationEventListener extends OrientationEventListener {
private static final String TAG = "CustomOrientationEvent";
private int prevOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
private Context context;
private final int ROTATION_O = 1;
private final int ROTATION_90 = 2;
private final int ROTATION_180 = 3;
private final int ROTATION_270 = 4;
private int rotation = 0;
public CustomOrientationEventListener(Context context) {
super(context);
this.context = context;
}
#Override
public void onOrientationChanged(int orientation) {
if (android.provider.Settings.System.getInt(context.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 0) == 0) // 0 = Auto Rotate Disabled
return;
int currentOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
if (orientation >= 340 || orientation < 20 && rotation != ROTATION_O) {
currentOrientation = Surface.ROTATION_0;
rotation = ROTATION_O;
} else if (orientation >= 70 && orientation < 110 && rotation != ROTATION_90) {
currentOrientation = Surface.ROTATION_90;
rotation = ROTATION_90;
} else if (orientation >= 160 && orientation < 200 && rotation != ROTATION_180) {
currentOrientation = Surface.ROTATION_180;
rotation = ROTATION_180;
} else if (orientation >= 250 && orientation < 290 && rotation != ROTATION_270) {
currentOrientation = Surface.ROTATION_270;
rotation = ROTATION_270;
}
if (prevOrientation != currentOrientation && orientation != OrientationEventListener.ORIENTATION_UNKNOWN) {
prevOrientation = currentOrientation;
if (currentOrientation != OrientationEventListener.ORIENTATION_UNKNOWN) {
onSimpleOrientationChanged(rotation);
}
}
}
public abstract void onSimpleOrientationChanged(int orientation);
}
Then add below line to the Android manifest under your activity tag
android:configChanges="orientation|keyboardHidden|screenSize"
Make sure that you do not add android:screenOrientation property in manifest for that activity.
Then use the CustomOrientationEventListener class inside onCreate of your camera activity
public class YourActivity extends AppCompatActivity {
private CustomOrientationEventListener customOrientationEventListener;
final int ROTATION_O = 1;
final int ROTATION_90 = 2;
final int ROTATION_180 = 3;
final int ROTATION_270 = 4;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
.....
customOrientationEventListener = new
CustomOrientationEventListener(getBaseContext()) {
#Override
public void onSimpleOrientationChanged(int orientation) {
switch(orientation){
case ROTATION_O:
//rotate as on portrait
yourButton.animate().rotation(0).setDuration(500).start();
break;
case ROTATION_90:
//rotate as left on top
yourButton.animate().rotation(-90).setDuration(500).start();
break;
case ROTATION_270:
//rotate as right on top
yourButton.animate().rotation(90).setDuration(500).start();
break;
case ROTATION_180:
//rotate as upside down
yourButton.animate().rotation(180).setDuration(500).start();
break;
}
}
};
}
#Override
protected void onResume() {
super.onResume();
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
customOrientationEventListener.enable();
}
#Override
protected void onPause() {
super.onPause();
customOrientationEventListener.disable();
}
#Override
protected void onDestroy() {
super.onDestroy();
customOrientationEventListener.disable();
}
}
I have set am activity to handle configuration changes and it works, meaning that onConfigurationChanged() is called when the orientation changes.
The activity has a button to explicitly change the orientation. When clicked, it called setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT).
Then the orientation is irrevocably set and onConfigurationChanged() is not called anymore.
How can I change the orientation when the user clicks the button while not loosing the onConfigurationChanged() callback ?
This is how I solved it. I am aware it is reinventing the wheel but it meets my requirement and I did not find a proper way to handle this with standard sdk tools.
First, create an OrientationManager class that listen to orientation changes
public class OrientationManager extends OrientationEventListener{
private static final String TAG = OrientationManager.class.getName();
private int previousAngle;
private int previousOrientation;
private Context context;
private OrientationChangeListener orientationChangeListener;
private static OrientationManager instance;
private OrientationManager(Context context) {
super(context);
this.context = context;
}
public static OrientationManager getInstance(Context context){
if (instance == null){
instance = new OrientationManager(context);
}
return instance;
}
public int getOrientation(){
return previousOrientation;
}
public void setOrientation(int orientation){
this.previousOrientation = orientation;
}
#Override
public void onOrientationChanged(int orientation) {
if (orientation == -1)
return;
if(previousOrientation == 0){
previousOrientation = context.getResources().getConfiguration().orientation;
if (orientationChangeListener != null){
orientationChangeListener.onOrientationChanged(previousOrientation);
}
}
if (previousOrientation == Configuration.ORIENTATION_LANDSCAPE &&
((previousAngle > 10 && orientation <= 10) ||
(previousAngle < 350 && previousAngle > 270 && orientation >= 350)) ){
if (orientationChangeListener != null){
orientationChangeListener.onOrientationChanged(Configuration.ORIENTATION_PORTRAIT);
}
previousOrientation = Configuration.ORIENTATION_PORTRAIT;
}
if (previousOrientation == Configuration.ORIENTATION_PORTRAIT &&
((previousAngle <90 && orientation >= 90 && orientation <270) ||
(previousAngle > 280 && orientation <= 280 && orientation > 180)) ){
if (orientationChangeListener != null){
orientationChangeListener.onOrientationChanged(Configuration.ORIENTATION_LANDSCAPE);
}
previousOrientation = Configuration.ORIENTATION_LANDSCAPE;
}
previousAngle = orientation;
}
public void setOrientationChangedListener(OrientationChangeListener l){
this.orientationChangeListener = l;
}
public interface OrientationChangeListener{
public void onOrientationChanged(int newOrientation);
}
}
Then in your activity implement OrientationChangeListener and override onOrientationChanged():
public class MyActivity extends Activity implements OrientationChangeListener{
private OrientationManager orientationManager;
#Override
public void onCreate(Bundle b){
orientationManager = OrientationManager.getInstance(this);
orientationManager.setOrientationChangedListener(this);
}
#Override
public void onOrientationChanged(int newOrientation) {
orientation = newOrientation;
if (newOrientation == Configuration.ORIENTATION_LANDSCAPE){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
setLandscapeConfig();
}else{
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setPortraitConfig();
}
}
So I don't use onConfigurationChanged anymore but keep the following line in the Manifest:
android:configChanges="orientation|screenSize"
Calling setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); will reactivate onConfigurationChanged. You can set up a timer like this:
// Force orientation to portrait
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
// Reactivate sensor orientation after delay
Timer mRestoreOrientation = new Timer();
mRestoreOrientation.schedule(new TimerTask() {
#Override
public void run() {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}
}, 2000);
We can only suppose the user will turn the device by himself to the forced orientation within the delay, and this can lead to bad user experience.
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT)
This makes your onConfigurationChanged to stop working. If you want it to work, try adding this to your manifest within that activity:
android:configChanges="orientation|screenSize"
The screenSize attribute is only for API 13+ so if your below that, you don't need it
..after many search this the right code mix that solve. enjoy!
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
OrientationEventListener orientationEventListener = new
OrientationEventListener(getApplicationContext()) {
#Override
public void onOrientationChanged(int orientation) {
boolean isPortrait = isPortrait(orientation);
if (!isPortrait && savedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
savedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
} else if (isPortrait && savedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
savedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
}
}
};
orientationEventListener.enable();
}
private int savedOrientation;
private boolean isPortrait(int orientation)
{
if (orientation < 45 || orientation > 315) {
return true;
}
return false;
}
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
if(newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE)
{
currentOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
// do what you need in landscape mode....
}
else if(newConfig.orientation==Configuration.ORIENTATION_PORTRAIT)
{
currentOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
// do what you need in portrait mode....
}
}
public void rotateScreenByUIButton() {
if (currentOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
else
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
You just need to make the orientation back to SCREEN_ORIENTATION_UNSPECIFIED, the the onConfiguration change will be called again
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE)
->
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)