Extra Space added when changing screen orientation - android

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" />

Related

TabLayout and ViewPager disappearing after Orientation Change

Currently, I'm developing support for different orientations. I have a viewpager and tablayout for my landscape layout and only a single fragment for my portrait layout. When I launch the application in whichever orientation, the layouts work fine. However, when the orientation is changed during runtime, in this case from portrait to landscape, the viewpager and tablayout completely disappears from the screen, leaving only the fragment at parent height and width even though a weight is allocated.
This led me to believe that the layout is not changing properly. I do not have android:configurations applied to my manifest as well. Otherwise, other activities and fragments work fine when I have their orientation changed. For some reason, only this does not work. I'll attach the XML code below.
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/drawer"
tools:context=".HomeActivity">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
tools:ignore="UselessParent">
<fragment
android:id="#+id/none"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:tag="fragment_tag"
android:name="com.example.trackeths.HomeFragment" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_weight="1">
<com.google.android.material.tabs.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabGravity="fill"
app:tabMode="fixed"
app:tabTextColor="#fff"
app:tabIndicatorColor="#fff"
android:background="#color/colorPrimaryDark"
/>
<androidx.viewpager.widget.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/viewPager"/>
</LinearLayout>
After posting this question, suddenly had an epiphany that it could be a persistent fragment that overwrites my layouts (i.e. fragment from portrait mode stacks on landscape mode due to savedInstanceState).
Hence, changed the super call to null.
super.onCreate(null);
Got the idea from Fool-proof way to handle Fragment on orientation change if anyone's interested or is new to fragments like I am.

Why does my floating action button jumps to the top of the page when the app starts?

I have currently a problem with a recycler view and a floating action button in my android app. The button always jumps to the right top of the page when I start the app.
The RecyclerView and the Button are inside a fragment. Currently I am using a ConstraintLayout to say the Button should always appear at the right end of the screen. However, I also tried it with a RelativeLayout and CoordinatorLayout with anchor and gravity attributes. In Android Studio, the layout shows it correct, with the button at the bottom right side of the screen. As soon as I start the app on my phone, it appears on the top right side of the screen...
Layout preview:
When I start the app on my phone:
Here's my Code I am using right now for the fragment:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/fragment_bucketlist"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:background="#color/colorPrimary">
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_bucketList"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab_addToBucketList"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>
Thanks in advance for helping!
Try using the recyclerview and fab button within a CoordinatorLayout.
The attribute app:layout_anchorGravity: will specify how an object should be positioned relative to an anchor, on both the X and Y axes, within its parent’s bounds.
<android.support.design.widget.CoordinatorLayout
android:id="#+id/fragment_bucketlist"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimary">
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_bucketList"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/floating_action_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:scaleType="center"
android:src="#drawable/android_floating_action_button_icon"
app:layout_anchor="#id/rv_bucketList"
app:layout_anchorGravity="bottom|right|end"
app:borderWidth="1dp"
app:elevation="10dp" />
</android.support.design.widget.CoordinatorLayout>
I solved the problem using a RelativeLayout. There was a problem that the Floating Action Button always showed up on the bottom edge and "stucked" at the bottom navigation bar (HUAWEI devices). The attribute app:useCompatPadding="true" solved the issue.
Here is the updated code:
<?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"
android:id="#+id/fragment_bucketlist"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:background="#color/colorPrimary">
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_bucketList"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab_addToBucketList"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_edit"
app:useCompatPadding="true"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true" />
</RelativeLayout>

Adjust Items inside recycler view + orientation changes

I have this problem - I guess someone can surely put light on what the heck is going wrong here...
My overall flow goes like this - Activity(#+id/activity) shows a fragment(#+id/image_container) from screen bottom when a button is tapped(keyboard closes if present and fragment shown sliding upwards from bottom), this fragment shows a viewpager with page indicator in linear layout, viewpager shows another fragment which contains recycler view with horizontal gridlayoutmanager. This recycler view contains various imageview and i need to arrange them keeping my rows fixed say 3 but columns can be variable based on screen width and density. Imageview has fixed height and width.
This is my activity layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/activity">
<include
layout="#layout/toolbar"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_alignParentTop="true" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="4dp"
android:id="#+id/divider"
android:layout_below="#+id/toolbar"/>
<include
layout="#layout/edit_bar"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_below="#+id/divider"/>
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/edit_bar" />
<FrameLayout
android:id="#+id/image_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/container"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
// Fragment inside the image_container
<?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="wrap_content"
android:orientation="vertical"
android:weightSum="1">
<android.support.v4.view.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="12dp"
android:layout_weight=".9"/>
<LinearLayout
android:id="#+id/sliderDots"
android:layout_width="match_parent"
android:layout_height="0dp"
android:gravity="center_vertical|center_horizontal"
android:orientation="horizontal"
android:layout_weight=".1"/>
// Fragment inside viewpager
<?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="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="26dp"
android:paddingRight="26dp">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
// Item inside recycler view
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/imageView"
android:layout_width="48dp"
android:layout_height="48dp"
tools:visibility="visible"
android:layout_margin="6dp"/>
// Fragment code which gets added to image_container upon button tap
FragmentManager fm = activity.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.view_transition_up_from_bottom, R.anim.view_transition_down_to_bottom);
fragmentTransaction.add(R.id.image_container, new ImageFragment(activity.getApplicationContext())).commit();
Inside this ImageFragment i calculate the rows(this is fixed let's say 3) and columns(Math.round((dpWidth - 52) / 60)) - 52(26*2 - for both side of recycler view, 60 - space occupied my 1 item including width and margin(L+R)), hence i know the images to be shown in each page and pass it to ImageViewFragment containing the recycler view which is used by adapter.
I use
recyclerView.setLayoutManager(new CustomGridLayoutManager(getActivity(), 3, CustomGridLayoutManager.HORIZONTAL, false));
to make my recycler view and hence i use fixed rows.
So my question is -
1. I wrote the code to keep my rows fixed and calculate columns based on screen width but sometimes i see too much spacing from right side of recycler view to screen edge, i kept it fixed with 26 dp but it shows more that that. How can i implement this type of functionality where i see uniform spacing in grid form??
2. How to handle orientation change when grid fragment is open, my activity is not redrawn. as i see i can only override onConfigurationChanged.

Android Databinding view tag isn't correct on view:null

the question tag may be familiar in stackoverflow but I have some situation here. I want to achieve that my app will have a bottom menu bar which will be visible across the application. So I added a view and set it on my base activity Like following
#Override
public void setContentView(int layoutResID) {
fullLayout = (RelativeLayout) getLayoutInflater().inflate(R.layout.activity_base, null);
configureToolbar(fullLayout);
subActivityContent = (FrameLayout) fullLayout.findViewById(R.id.content_frame);
getLayoutInflater().inflate(layoutResID, subActivityContent, true);
super.setContentView(fullLayout);
}
Previously it was like:
#Override
public void setContentView(int layoutResID) {
View view = getLayoutInflater().inflate(layoutResID, null);
configureToolbar(view);
super.setContentView(view);
}
Now on some page there is data-binding. Which is called like following:
viewModel = new MyViewModel(someId, someName, false, emptyString);
binding = DataBindingUtil.setContentView(this, R.layout.activity_my_layout);
binding.setItem(viewModel);
Now I am getting error on 2nd line.
Here is my activity layouts. 1st one is common layout which is activity_base, 2nd one is data binding Layout.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent">
<include android:id="#+id/app_bar" layout="#layout/app_bar" />
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.roughike.bottombar.BottomBar
android:id="#+id/bottomBar"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
app:bb_tabXmlResource="#xml/bottombar_tabs" />
2nd layout:
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:map="http://schemas.android.com/apk/res-auto">
<data>
<import type="android.view.View" />
<variable
name="item"
type="io.ppp.views.someActivity" />
</data>
<RelativeLayout
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/root_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="io.ppp.views.someActivity">
<include android:id="#+id/app_bar" layout="#layout/app_bar" />
<!--<include layout="#layout/activity_base" />-->
<WebView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/webViewLoader"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<RelativeLayout
android:id="#+id/progress_indicator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="false"
android:layout_centerInParent="true"
android:visibility="#{item.loading ? View.VISIBLE : View.GONE}">
<ProgressBar
android:id="#+id/search_progress"
style="#style/Base.Widget.AppCompat.ProgressBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:indeterminate="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_gravity="center"
android:layout_marginTop="50dp"
android:text="#{item.loadingText}"
android:textAppearance="?android:attr/textAppearanceSmall" />
</RelativeLayout>
</RelativeLayout>
I don't think this is a good solution to implement a bottom navigation bar across your application since you are creating Activities, and it will be clear to the user that every time you change activity the screen will totally swap (bottom bar included) instead of keeping a fixed element in the bottom of the screen which the user will use to guide himself across the application.
Implementing Bottom Navigation in Android is much trickier than it is in iOS since you are going to have to work with ONE SINGLE Activity and Fragments(Lots of them if you have a lot of screens) to achieve a smooth bottom navigation like application.
My advice to you is to transform your activities into fragments, implement the bottom navigation Activity with the bottom bar and a fragment container, and go from there.
From API 25 it was introduced the BottomNavigationView which will make your life easier and you won't need to use BottomBar library from GitHub. I also advice to look at AHBottomNavigation, it seems to me more complete than the native one, gives you a better control and choices over your bottom bar.

Android: positioning of Floating Action Button unpredictable

Some of my floating action buttons don't remain where I want, and I cannot understand why.
The first is how they should be (and actually sometimes it works), the other two images show how they behave sometimes... and I cannot find a "pattern" in this behavior.
This is the layout (only one half):
<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/lay_attivita_edit_ubicazioni"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="#dimen/list_padding_lateral"
android:paddingRight="#dimen/list_padding_lateral">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:id="#+id/container_attivita_edit_origini">
<TextView
style="#style/FieldLabel"
android:layout_marginTop="20dp"
android:text="#string/attivita_edit_origini" />
<ListView
style="#style/ListView"
android:id="#+id/list_attivita_edit_origini"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:fadeScrollbars="false"
android:background="#drawable/border_rectangle" />
</LinearLayout>
</LinearLayout>
<android.support.design.widget.FloatingActionButton
style="#style/FloatingActionButton.Small"
android:id="#+id/fab_attivita_edit_ubicazioni_edit_origini"
app:layout_anchor="#id/list_attivita_edit_origini"
app:layout_anchorGravity="top|right|end" />
</android.support.design.widget.CoordinatorLayout>
I tried also to se anchor and anchorGravity programmatically but the result is the same. It could happen because depending on some logic one of the two sections could not be visible, in case I make them invisible at the end of OnCreateView.
It doesn't depend on the visibility of the "anchor list" because the fab move even if I always leave both the lists visible.
I tried also to change programmatically anchor and anchorId of the fab at every change of visibility of them or of their lists, nothing.
CoordinatorLayout.LayoutParams editOrigineFabParams = (CoordinatorLayout.LayoutParams)editOrigineFab.LayoutParameters;
editOrigineFabParams.AnchorId = Resource.Id.list_attivita_edit_origini;
editOrigineFabParams.AnchorGravity = (int)(GravityFlags.Top | GravityFlags.Right | GravityFlags.End);
editOrigineFab.LayoutParameters = editOrigineFabParams;
With the same conditions/code sometimes they work and sometimes they don't. It looks like a bug in Android. I tried with Android 7.0 and 7.1, Xamarin.Android.Support.Compat.25.3.1.
Anyone who had a similar problem or who has an idea of what could be the reason?
Use FAB by james montemagno.
Add FAB by james montemagno from nuget to your project.
https://www.nuget.org/packages/Refractored.FloatingActionButton/
<Refractored.Fab.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_margin="16dp"
android:src="#drawable/ic_action_content_new"
app:app_colorNormal="#color/primary"
app:app_colorPressed="#color/primary_pressed"
app:app_colorRipple="#color/ripple" />
use layout_gravity for positioning .
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:src="#drawable/ic_edit"
android:layout_marginRight="15dp"
android:layout_marginBottom="15dp" / >

Categories

Resources