SurfaceView rotation issue on Android 6 - android

I have a simple activity running my OpenCV application. The app should detect objects from camera and visualize them on a custom SurfaceView. I want to lock the device orientation in portrait mode and rotate my widgets programmatically as the standard camera app does.
Here is the activity layout. It includes OpenCV CameraView and a fragment widget shown above it.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:opencv="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.chessking.android.vision.ui.widget.ExtendedCameraView
android:id="#+id/track_camera_preview"
android:layout_width="match_parent"
android:layout_height="match_parent"
opencv:camera_id="any"
opencv:show_fps="true"/>
<FrameLayout
android:id="#+id/track_fragment_container"
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true">
<fragment
android:id="#+id/track_board_preview"
class="com.chessking.android.vision.ui.BoardWidgetFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
<Button
android:id="#+id/track_action"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:padding="16dp"
android:text="#string/scan_action"/>
</RelativeLayout>
Custom SurfaceView is presented in the fragment layout. It is com.convekta.android.chessboard.ChessPanel
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/board_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/boardBackground"
android:orientation="vertical">
<include layout="#layout/widget_board_clock_both" />
<com.convekta.android.chessboard.ChessPanel
android:id="#+id/board_panel"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#color/board_background_transparent"
app:chessPanelBackground="#color/board_background_transparent"
app:chessPanelBorderColor="#color/board_border"
app:chessPanelBorderWidth="1dp"/>
<com.convekta.android.chessboard.NotationView
android:id="#+id/nota"
android:layout_width="match_parent"
android:layout_height="20dp"
android:clipChildren="false"
android:fadeScrollbars="false" />
</LinearLayout>
When I need to rotate the widget layour, I change rotation property of the board_layout.
boardLayout.rotation = degrees.toFloat()
The problem is the rotation works on Android 9, but the canvas is misplaced on Android. Here are screenshots from Android 6 emulator, in portrait mode the app looks normal, in landscape SurfaceView jumps out of its layout.

In the <activity> tag of AndroidManifest.xml, add the line android:screenOrientation="portrait"

Related

Change the quality of an ImageView

I'm trying to make a splash screen, I'm doing that with react native, but I'm using android studio to create the style.
First of all, I'm following this video that uses this library.
I have the following code of my splash screen:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/primary"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
>
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="#drawable/launch_screen"
android:scaleType="centerCrop" />
</LinearLayout>
</RelativeLayout>
It looks like this:
As you can see, the quality of the logo is low, and I would like to make it better.
My drawable folder is the following:
Thanks!
It seems that your launch_screen.png file has a small resolution.
Change that file with bigger resolution with better quality.

How to prevent reverse-landscape orientation but allow landscape orientation in Android?

I have an Activity where i want the view to be on left side of the device(opposite side of volume/power button) in all cases.
I have no problem doing this in portrait and landscape orientation for the Activity, but when it goes to reverse-landscape and reverse-portrait the view will go to the right side of the device(volume/power button side).
Is it possible to allow screen orientation changes but block reverse-orientations?
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<CustomView
android:layout_width="150dp"
android:layout_height="wrap_content"
>
</CustomView>
<include
layout="#layout/some_layout"
>
</include>
</LinearLayout>
activity_main.xml(land):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<CustomView
android:layout_width="wrap_content"
android:layout_height="150dp">
</CustomView>
<include layout="#layout/some_Other_layout" />
</LinearLayout>
I have tried orientationListener, whenever it goes to reverse-landscape i try to set orientation to landscape and then release the orientation by setting unspecified but that did not work as screen was getting locked and further changes in orientation where not getting detected.
Any ideas on how this can be solved?
You can prevent the reverse landscape as below Kotlin code
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
You can use below Java code
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

Extra Space added when changing screen orientation

My app adds fragments with values to the main activity at runtime but I need to be able to change the screen orientation without losing those values. The main issue is my adding of android:configChanges="orientation|screenSize" to the manifest works, but a large amount of extra space is added to the top of the app, so at either orientation after the first change, about a fourth of the screen is inaccessible white space.
activity_main.xml
<android.support.design.widget.AppBarLayout
android:id="#+id/app_bar"
android:layout_width="match_parent"
android:layout_height="50dp"
android:fitsSystemWindows="true"
android:theme="#style/MyAppTheme">
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_main" />
</android.support.design.widget.CoordinatorLayout>
content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="25dp"
android:fillViewport="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".MainActivity"
tools:showIn="#layout/activity_main">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="60dp"
android:layout_marginTop="8dp">
<TextView
android:id="#+id/manu_label"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:text="Manufacturer:"
android:textSize="12sp"
android:gravity="center"
android:layout_marginBottom="4dp"
android:layout_marginLeft="8dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"/>
<Spinner
android:id="#+id/manu_spinner"
android:theme="#style/SpinnerStyle"
android:layout_width="80dp"
android:layout_height="20dp"
android:dropDownWidth="150dp"
android:layout_marginLeft="8dp"
android:background="#drawable/cell_background"
android:layout_toRightOf="#id/manu_label"
android:layout_alignParentTop="true">
</Spinner>
<LinearLayout
android:id="#+id/panels_container"
android:orientation="vertical"
android:layout_below="#id/manu_spinner"
android:layout_alignParentLeft="true"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</LinearLayout>
</RelativeLayout>
</android.support.v4.widget.NestedScrollView>
My java code does not manipulate the view except to add fragments to a linear layout:
private View.OnClickListener cableListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentTransaction ft = manager.beginTransaction();
PanelsFragment frag = PanelsFragment.newInstance();
cables.add(frag);
ft.add(R.id.panels_container, frag, Integer.toString(trans.indexOf(frag)));
ft.commit();
}
};
Is there a way to prevent the extra space between my app bar and the scrollview, or do I need a different strategy? I did try overriding the onSaveInstanceState and onRestoreInstanceState, but my methods supposedly required a higher API than my minimum of 14. Any suggestions would be appreciated.
EDIT: Due to the nature of the project, I cannot provide a picture of the issue. When the app first starts, there is almost no space between the label and spinner with "manu" id's and the app bar. However, when the screen goes from portrait to landscape, at least 60dp of inaccessible space is between the app bar and the label and spinner. I noted that the 25dp of top margin for the content view was needed otherwise its contents started behind the app bar.
My problem was unexpectedly solved by specifying the height, width and margins for the content view in activity_main.xml:
<include
layout="#layout/content_main"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_marginTop="0dp" />

Navigation Drawer and SurfaceView in fragment

I want to use SurfeceView to make simple painting app like MS Paint.
I created main activity with navigation drawer as toolbox for painting tools.
I assumed that user I can operate on many surfaces (pages) so I made for each page separate fragment with SurfaceView inside.
In main activity I made customized button to open drawer.
In fragment I set mSurfaceView.setZOrderOnTop(true) for SurfaveView and in SurfaceView mHolder.setFormat(PixelFormat.TRANSLUCENT)
Fragment layout:
<?xml version="1.0" encoding="utf-8"?>
<it.controls.PaintPageLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="20dp"
android:background="#e0aa66cc"
android:visibility="visible">
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="Sv"
android:textSize="12sp"
android:padding="0dp"
android:background="#ffff4444"
android:textColor="#android:color/black"
android:minWidth="40dp"
android:id="#+id/surface_fragment_debug_save" />
<TextView
android:id="#+id/surface_fragment_debug_info"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="end"
android:text="debug_info"
android:textColor="#android:color/white"
android:background="#android:color/transparent"
android:visibility="visible"
android:layout_toEndOf="#+id/surface_fragment_debug_save" />
</RelativeLayout>
<it.controls.PaintSurfaceView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/surface_fragment_surface"
/>
Main layout is almost standard template generated from Android Studio, expect that my app is full screen (doesn't have Toolbar)
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<!-- The main content view -->
<android.support.design.widget.CoordinatorLayout
android:id="#+id/main_coordinate_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<!-- button to show left menu -->
<android.support.v7.widget.AppCompatImageButton
android:id="#+id/toolbox_toggle_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/toolbox_show_margin"
android:layout_marginLeft="#dimen/toolbox_show_margin"
android:contentDescription="#string/menu_show_hide_menu"
android:src="#drawable/ic_menu_black_48dp"
android:minWidth="#dimen/toolbox_show_button_size"
android:minHeight="#dimen/toolbox_show_button_size"
android:scaleType="fitCenter"
android:background="#drawable/toolbox_new_page_button_border"
/>
</android.support.design.widget.CoordinatorLayout>
<!-- The navigation drawer -->
<FrameLayout
android:id="#+id/menu_container"
android:layout_width="#dimen/nav_drawer_width"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="horizontal"
android:layout_gravity="start"
tools:ignore="UselessParent">
</FrameLayout>
</android.support.v4.widget.DrawerLayout>
When I coded that I made simple drawing mechanism to draw path in SurfaceView and there is a problem.
My problem is that after I draw path I would like to change color so I must open toolbox (drawer). After I open drawer I saw that path is painted ON drawer as on screen below.
What I made wrong? How to hide SurfaceView behind drawer?
Your app has two distinct layers: the View UI layer, and the SurfaceView Surface layer. One of them is entirely on top of the other. You can't put one partially under the other. You put the SurfaceView Surface on top, so it's in front of all of your Views.
You might be better off with a custom View, rather than a SurfaceView. It'll mix in with your other Views, and for Canvas rendering it can be more efficient because it'll take advantage of hardware-accelerated rendering.

Strange behaviour when trying to restrict a view in RelativeLayout

I am trying to add a dynamic Bounding box to my camera layout,I have the following xml code in which I am trying to keep the bounding box from reaching the ShutterButton,I find that the box goes underneath the ShutterButton,I think it is because overlapping of views is allowed in RelativeLayout...
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/container"
android:layout_alignParentTop="true"
android:layout_above="#+id/btn_capture"
/>
<com.example.mycameraapp.RectangleView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#id/btn_capture"
android:id="#+id/bound_box"
/>
<com.example.mycameraapp.ShutterButton android:id="#id/btn_capture"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:src="#drawable/ic_launcher"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
I would like it to not work in the region where ShutterButton specifically is,such that the ShutterButton remains the top Z element followed by the RectangleView on top of the CameraPreview which is simply a SurfaceView
Your btn_capture was not created before you referenced it. Whenever you assign ids use #+id and whenever you refer ids use #id for avoiding errors
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.mycameraapp.ShutterButton android:id="#+id/btn_capture"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:src="#drawable/ic_launcher"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<FrameLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/container"
android:layout_alignParentTop="true"
android:layout_above="#id/btn_capture"
/>
<com.example.mycameraapp.RectangleView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#id/btn_capture"
android:id="#+id/bound_box"
/>
Adding the RectangleView in my Java code as a child of the FrameLayout helped.Now,it draws itself behind the ShutterButton and allows me to click the Button even if it is drawn behind the ShutterButton.
mPreview=new CameraPreview(this,mCamera);
mBox=new RectangleView(this);
container.addView(mPreview);
container.addView(mBox);
In onPause,container.removeAllViews(); ensures that the RectangleView is removed as well

Categories

Resources