I am facing a problem. I have a custom layout for toolbar and in my activity xml, I am including this toolbar. The structure of my activity is:
Toolbar layout on top using include tag.
The ViewPager
TabLayout at bottom to get bottom tabs.
The problem I am facing is that on some devices, it is coming out perfect but in a few devices (tested on moto G series devices) the bottom tab is leaving space.
Please Refer the Images below:
In Normal Phones when it shows expected UI
In MOTO G series
The xml code is following
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#efeded"
android:weightSum="11"
android:orientation="vertical">
<include layout="#layout/custom_tool_bar" />
<android.support.v4.view.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="10" />
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
style="#style/BottomTabLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#fff"
android:layout_weight="1"
app:tabIndicatorColor="#color/colorPrimaryDark"
app:tabSelectedTextColor="#color/colorPrimaryDark"
/>
</LinearLayout>
For bottom tabs you can use bottomnavigationview it provides better performance and works in MOTO devices with out any problem. Check this
https://developer.android.com/reference/android/support/design/widget/BottomNavigationView.html
remove android:weightSum=11 attribute in your parent LinearLayout;
change ViewPager's android:layout_weight=10 attribute to android:layout_weight=1;
remove TabLayout's android:layout_weight=1 attribute
and try again.
I found the problem why is it happening. I have used a library - ResideMenu in my Activity and it has a function to detect whether the device has hardware Back and Menu buttons or the digital ones.
#Override
protected boolean fitSystemWindows(Rect insets) {
int bottomPadding = viewActivity.getPaddingBottom() + insets.bottom;
boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
boolean hasHomeKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_HOME);
if (!hasBackKey || !hasHomeKey) {//there's a navigation bar
bottomPadding += getNavigationBarHeight();
}
this.setPadding(viewActivity.getPaddingLeft() + insets.left,
viewActivity.getPaddingTop() + insets.top,
viewActivity.getPaddingRight() + insets.right,
bottomPadding);
insets.left = insets.top = insets.right = insets.bottom = 0;
return true;
}
This is not working properly. For some devices it works fine but for some devices it's not able to determine the buttons. So in some devices it is going up leaving a space for digital buttons.
Anyways, I could not find a solution for this, tried a few StackOverflow but it didn't work out, please post if anyone finds something.
Related
I use Linear Layout inside a Relative Layout. Because of this, the action bar is not showing up. It works fine both on Android 5 and 6. This problem only occurs in Android 4. Could you please help me?
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.blabla">
<LinearLayout
android:paddingTop="60dp"
android:paddingLeft="#dimen/act_left"
android:paddingRight="10dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:background="#color/background_gray_soft">
....
</LinearLayout>
</RelativeLayout>
For those who uses FrameLayouts with Fragments in ICS, do not change your background with
android:backgound="..."
It makes the Toolbar color same with your background.(I have no idea why. Still trying to figure it out.)
You need to check your API version in your Java code and set the background color there.
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
FrameLayout frameLayout = (FrameLayout) findViewById(R.id.fragment_container);
frameLayout.setBackgroundColor(getResources().getColor(R.color.background_gray_soft));
}
There is only one problem left and that could not be solved with this method.
If you want to have a special background color in ICS(I only encountered this problem with Fragments), how will you set that?
I'm updating an app to use the new Toolbar instead of the regular ActionBar.
In my app the user must be able to select a contact from their contact list. To do so, I've added a SearchView to the menu.
The contacts are already in the list; the SearchView is used to filter the list using the ArrayAdapter.getFilter() method.
It all worked fine using the ActionBar, but the Toolbar's height gets stretched to just behind the keyboard. Using the XML inspection from Android Device Monitor I can see the ListView exists behind my keyboard.
It almost seems as if the SearchView wants to display suggestions, but I have no such thing configured. Any idea what's going wrong?
The images illustrate the problem. They show the normal, expanded and focused state of the SearchView.
This is my XML menu:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/action_forwarding_contact_search"
app:showAsAction="always"
android:title="#string/forwarding_contact_search"
app:actionViewClass="android.support.v7.widget.SearchView"
android:icon="#drawable/abc_ic_search_api_mtrl_alpha"/>
</menu>
Edit
Giving the Toolbar a fixed height doesn't solve the problem, because it will make SearchView disappear when it has focus. Changing the gravity of either item seems to have no effect on the SearchView.
I had the same problem than OP, I tried the android:fitsSystemWindows="true" solution, but it was half resolved: the searchview didn't expand anymore but the notification bar (top of screen) became totally white (like the layout background) instead of red (my app theme).
I found an alternative way and it's working like a charm, so for those who are stuck, try this:
In your manifest, just add this line in your activity section:
android:windowSoftInputMode="adjustPan"
Example:
<activity
android:name=".MainActivity"
android:windowSoftInputMode="adjustPan"
android:label="My main activity" >
</activity>
Ok, I figured it out. There was no problem with the SearchView, because the same happened with ordinary EditTexts which were placed normally inside a layout xml. The Toolbar wasn't the problem either.
I created an empty activity and played around with anything I changed in my app and finally came to my theme. On KitKat and later I had <item name="android:windowTranslucentStatus">true</item> set on the theme, so the navigation drawer would appear behind the status bar.
Disabling/removing this would resolve the issue. This reminded me of the android:fitsSystemWindows="true" property. It is set on the Toolbar, but not in the layout xml of the main activity that contains the DrawerLayout.
I guess the DrawerLayout sets itself to fit the system windows.
E.g. there's no fitSystemWindows property here:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DashboardActivity">
The activity where the problem occurred did not have a NavigationDrawer, it was a new activity. Setting android:fitsSystemWindows="true" on the root node of the layout of the activity made things work fine.
So, for anyone to read this: if you have <item name="android:windowTranslucentStatus">true</item> in your theme, make sure any root node containing a toolbar contains a android:fitsSystemWindows="true".
Working sample:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<include layout="#layout/toolbar" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="#+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true" />
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Button" />
</LinearLayout>
</LinearLayout>
I had same issue like this but did't help above answers but after lots of search found something.
may help you too.!!
after add this attribute in toolbar
android:layout_height="?attr/actionBarSize"
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
style="#style/ToolBarStyle"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/myPrimaryColor"
android:minHeight="#dimen/abc_action_bar_default_height_material" >
<TextView
android:id="#+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textColor="#color/myTextPrimaryColor"
android:layout_gravity="center" />
</android.support.v7.widget.Toolbar>
The accepted answer works fine, however I needed an alternative that would allow to view the Toolbar under translucent status bar.
The problem is that Toolbar uses paddings to cover for system components. As a result, the paddingBottom of the Toolbar is being set to soft keyboard's height whenever the keyboard appears. Solution was to reset the padding before calling super.onMeasure in my custom Toolbar class:
public class MyToolbar extends Toolbar {
(...)
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), 0);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
It seems like a old question but I want to address the real cause about this issue.
In fact, the fitsSystemWindows does not only add statusBar insets into your views padding, but also keyboard's height. So, when keyboard showed, your toolbar(which is the view who consumes window insets) will gain a bottom padding equals to your keyboard's height.
Move fitSystemWindows to root node do solve this problem, but sometimes we can't do that, for example we need toolbar's background to fill the statusbar.
So, the real solution for this issue, I think, is to tell view only consume top insets. Luckily, Android do offer a method for us to do that.
private static final View.OnApplyWindowInsetsListener CONSUME_TOP_INSET_LISTENER = new View.OnApplyWindowInsetsListener() {
#RequiresApi(api = Build.VERSION_CODES.KITKAT_WATCH)
#Override
public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
int b = v.getPaddingBottom();
int l = v.getPaddingLeft();
int r = v.getPaddingRight();
v.setPadding(l, insets.getSystemWindowInsetTop(), r, b);
int il = insets.getSystemWindowInsetLeft();
int ir = insets.getSystemWindowInsetRight();
int ib = insets.getSystemWindowInsetBottom();
return insets.replaceSystemWindowInsets(il, 0, ir, ib);
}
};
public static void makeViewConsumeTopWindowInsetsOnly(#NonNull View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
view.setOnApplyWindowInsetsListener(CONSUME_TOP_INSET_LISTENER);
}
}
Add above code to some place, and call this method with the view you want to consumes top insets.
I ran into a similar issue and setting showAsAction="always|collapseActionView" inside the Search Menu Item (menu.xml) solved the stretching of the toolbar for me.
I had the same issue with a SearchView on a Toolbar with a TextView and Spinner in it. Closing the SearchView (either by pressing the Toolbar back button or by switching to a different tab in the ViewPager) caused the Toolbar to stretch out to just below the top of the keyboard.
I solved it by placing an extra layout around the views in my Toolbar.
Before:
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<Spinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</android.support.v7.widget.Toolbar>
After
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<Spinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</android.support.v7.widget.Toolbar>
simplest solution without changing xml and keeping translucent system bar is to add:
kotlin:
toolbar.setOnApplyWindowInsetsListener { toolbar, windowInsets ->
toolbar.updatePadding(
windowInsets.systemWindowInsetLeft,
windowInsets.systemWindowInsetTop,
windowInsets.systemWindowInsetRight,
0
)
windowInsets.consumeSystemWindowInsets()
}
please check if your fitsSystemWindows=true are placed correctly.
I would like to share my experience but before that I want to dropped this comment. So far, I really find this CoordinatorLayout shenanigans buggy and not worthy of being dropped in the SDK. Its just buggy. When it behaves like this erratically, the architecture on the xml layout is not much of a help to figure out whats going on. I followed the examples religiously and none of them worked.
Having said that, I am using the build tools version v24.0.2 (The latest as of this writing) and my situation may be of different than the rest. So I am putting this answer along with other answers here.
In my case, I am using this library for NavigationDrawer
As some answers here pointed out, its the navigation drawer. I tried not using that library and still having the problem. I have CoordinatorLayout as the parent layout of my two activities and programatically inserts the NavigationDrawer as instructed by the library author. The expanding Toolbar the size of the screen when focusing on an EditText is still there. Therefore, in my case, the problem is not coming from there.
Here's what I did in my case:
I removedfitsSystemWindows from the CoordinatorLayout layout of the activity. Contrary to what other people suggested here.
I am pasting my entire activity layout here:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/coordinatorlayout_homescreen"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.HomeScreenActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsingtoolbarlayout_homescreen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginStart="64dp"
app:expandedTitleMarginEnd="48dp"
app:layout_scrollFlags="scroll|enterAlwaysCollapsed">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar_homescreen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:layout_collapseMode="pin"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<FrameLayout
android:id="#+id/framelayout_homescreen"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.NestedScrollView>
<!--
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab_homescreen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="#dimen/fab_margin"
android:src="#android:drawable/ic_dialog_email" />
-->
</android.support.design.widget.CoordinatorLayout>
I did this on another activity and it works as expected. I don't have the expanding Toolbar anymore. But this problem occurred. I am about to pull my hair out. The status bar became white. Phoenix Wang solution on that post fix it for me and I quote his answer:
I found the answer in this link:Status Bar Color not changing with
Relative Layout as root element
So it turns out we need remove the
<item name="android:statusBarColor">#android:color/transparent</item> in
styles.xml(v21). And it works just fine for me.
My only concern is how will this solution holds in the upcoming updates. CoordinatorLayout should not be behaving like that.
In case you are using an EditText inside Toolbar, adding "flagNoExtractUi" in imeOptions , will solve the stretching edit area.
EditText for Search Action without stretching:
android:id="#+id/toolbar_editText"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:inputType="text"
android:imeOptions="actionSearch|flagNoExtractUi"
android:singleLine="true" />
I am migrating to the new Toolbar feature in appcompat v21 from the previous action bar. I still want to keep the logo on the top left part of the actionbar (toolbar). For doing I added in my layout the support toolbar and I created a new thene for it.
app:theme="#style/NewToolBarStyle"
I am adding the log programmatically as there is some logic in the app for this.
actionBar.setLogo(R.drawable.myicon);
Referring to my new style (empty for the moment):
<style name="NewToolBarStyle" parent="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
</style>
However the result is showing an image the is too big for what I am looking for, and I am wondering how to reduce the size of the icon.
Is there any way (style, layout or programming) that I can reduce the logo size?
There is no logo icon in material design : http://www.google.com/design/spec/layout/structure.html#, so I suppose this is not well tested scenerio - or simply (broken) by design. You can add ImageView as a child widget of your toolbar and use it to show any image. It will show on the right of all the other internal widgets - like spinner - but list navigation mode is also deprecated.
If you insist on having logo then my workaround for this is to make sure toolbar is of fixed height - this takes care of wrong icon height. Even after that you will have to set setAdjustViewBounds to true on toolbars internal logo ImageView - otherwise it will create large left and right padding.
This is how my toolbar looks like (height set to ?attr/actionBarSize):
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/toolbar"
android:layout_height="?attr/actionBarSize"
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light">
</android.support.v7.widget.Toolbar>
reference it inside your activity layout using:
<include layout="#layout/toolbar_actionbar"/>
dont change layout_height in include.
The second step is to setAdjustViewBounds(true) on logo icon:
Drawable logo = getDrawable(iconRes);
toolbar.setLogo(logo);
for (int i = 0; i < toolbar.getChildCount(); i++) {
View child = toolbar.getChildAt(i);
if (child != null)
if (child.getClass() == ImageView.class) {
ImageView iv2 = (ImageView) child;
if ( iv2.getDrawable() == logo ) {
iv2.setAdjustViewBounds(true);
}
}
}
Following the suggestiong give by #brightstar I would like to develop further the answer.
The best way to control the size and position of the Logo in the new Toolbar is by actually not using it. The concept is completely different, what you need to do is create a toolbar from scratch. So you need to make a decision, either you use the layout given by the actionBar or include everything new including the title.
If you stop using the logo but you keep using the title you finally will see that the logo is over the title creating and ood situation.
So, an example of what to do is the following:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/action_bar_background"
app:theme="#style/NewToolBarStyle"
android:minHeight="?attr/actionBarSize" />
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="#+id/text_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="17dp"
android:textSize="20sp"
android:layout_toRightOf="#+id/logo_image"
android:text="#string/app_name"
android:textColor="#color/white" />
<ImageView
android:id="#+id/logo_image"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:scaleType="centerInside" />
</RelativeLayout>
</FrameLayout>
You create this file as my_toolbar.xml. Notice the following details:
I did not include an src of my ImageView because I am changing it dinamically. But works adding it.
I used a relative layout for being able to center the icon and the text.
I need still to include the Home button.
Later on as described by #brightstar you need to include in the top of your layouts by an include, however.... remember to add an id so that you can refere all your other Views to it.
<include layout="#layout/toolbar_sharemup"
android:id="#+id/including" />
I've been trying to reproduce the way that the Contacts app on version 5.0 collapses the toolbar when the listview is scrolled.
Gallery of screenshots demonstrating the desired interaction
Note the collapse of the toolbar in stages, where it displays search+last contact, fades last contact, collapses last contact, collapses search, leaving only the tabs.
So far, I have a toolbar sitting above a recyclerview in a LinearLayout, and the toolbar is used as an actionbar, not standalone.
I can't figure out how to intercept the touch event on the recyclerview and make it shrink the toolbar, and then return the scroll event to the recyclerview. I tried putting the entire thing in a scrollview, but then the recyclerview couldn't calculate it's height properly and displayed no content. I tried overriding onscroll on the recyclerview, and found that it will only notify me when a scroll event started, and provide me with the first visible card id.
The way that looks right, but I can't get working for the life of me, is this:
getSupportActionBar().setHideOnContentScrollEnabled(true);
Which returns:
Caused by: java.lang.UnsupportedOperationException: Hide on content scroll is not supported in this action bar configuration.
Using a traditional actionbar, putting a toolbar below it, and setting hideoncontentscrollenabled also didn't work, scrolling never triggered the hide method on the actionbar.
-- edit --
I was able to get hideOnContentScrollEnabled working on a listview with a traditional actionbar, but the behavior is not the same as the contacts app. This is clearly not the method they used-- it simply triggers .hide() on the actionbar when a fling event occurs on a listview, which is notably different from the contacts app, which drags the toolbar along with the scroll event.
-- /edit --
So I abandoned that route, and put fill_parent on the cardview height, and animated a collapse on the toolbar. But how do I trigger it so that it follows the touch event and then returns the touch event to the recyclerview?
activity_main.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/actionBarSize"
android:background="#color/colorPrimary"
/>
<fragment android:name="me.myapplication.FragmentTab"
android:id="#+id/tab_fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
fragment_layout.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:gravity="center_horizontal"
android:orientation="vertical"
android:padding="8dp"
android:background="#eeeeee"
>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
styles.xml
...
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
...
MainActivity.java
Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
// Disable the logo in the actionbar, as per material guidelines
toolbar.getMenu().clear();
toolbar.setTitle("My toolbar");
setSupportActionBar(toolbar);
I haven't investigated the source code yet but this guy seems to have made life easy yet enlightening.
https://github.com/ksoichiro/Android-ObservableScrollView
EDIT
Google has just released Android Design Library. Please take a look as it contains all the effects of collapsing toolbars and much more.
Well, I have no idea how they do it, but... why don't you take a peek to the source code? Luckily for us, the Contacts app is still open-source on Android L (others weren't as lucky as Contacts, like Mail, which does not work anymore on L; or Keyboard, which they stopped updating anymore since the launch of their propietary Google Keyboard).
Anyway, here's the source code I think you should look at:
https://github.com/android/platform_packages_apps_contacts/blob/master/src%2Fcom%2Fandroid%2Fcontacts%2Factivities%2FActionBarAdapter.java
Note the method update(boolean skipAnimation) in Line 311, which calls animateTabHeightChange(int start, int end) (Line 437).
My guess is all the magic happens there ;-)
As of June 2015, your desired effect can be accomplished via the so called CollapsingToolbarLayout of the new design support library.
Based on the sample code here, I am figuring that:
the search cardview is child of the toolbar
the missed call cardview belongs to the collapsingtoolbar with the collapseMode attribute set to pin
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="112dp"
android:fitsSystemWindows="true"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="?attr/actionBarSize"
android:fitsSystemWindows="true"
app:layout_scrollFlags="scroll|enterAlwaysCollapsed|enterAlways">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:fitsSystemWindows="false"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:layout_collapseMode="pin"
app:layout_scrollFlags="scroll|enterAlways">
<!-- Search layout -->
<android.support.v7.widget.CardView
</android.support.v7.widget.CardView>
</android.support.v7.widget.Toolbar>
<!-- Last call card view-->
<android.support.v7.widget.CardView
app:layout_collapseMode="pin">
</android.support.v7.widget.CardView>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="#color/primary_color"
app:layout_scrollFlags="scroll"/>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
No third party library is required now! Android is officially providing library. You can collapse the toolbar and do many other tweaks.
Check this android-developer's blog
And don't forget to add this dependency in your build.gradle file.
compile 'com.android.support:design:22.2.0'
I found this library that seems to do what you're looking for: https://github.com/kmshack/Android-ParallaxHeaderViewPager and this https://github.com/flavienlaurent/NotBoringActionBar
You can play the video to see the behavior: https://www.youtube.com/watch?v=sCP-b0a1x5Y
It might not be the 'new' standard way of doing it with ToolBar, but it might give you an idea by inspecting the code. It seems to attach a OnScrollListener to the scrolling content and then trigger changes on the size of the bar.
For me https://mzgreen.github.io/2015/06/23/How-to-hideshow-Toolbar-when-list-is-scrolling%28part3%29/ has helped. A source code is found here: https://github.com/mzgreen/HideOnScrollExample/tree/master/app/src/main.
A RecycleView in your layout should look like:
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
Note that after starting an application 2 toolbars appear (actionbar and toolbar). So in your activity.java you should write so:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Hide ActionBar.
supportRequestWindowFeature(WindowCompat.FEATURE_ACTION_BAR);
getSupportActionBar().hide();
setContentView(R.layout.your_activity_layout);
...
The toolbar is customized as shown here: https://stackoverflow.com/a/26548766/2914140. I mean, it appears without title and any other elements, so you can add them in a layout.
Android's Contact app doesn't have an easy plug-and-play solution that you can grab for use in your own app.
It does a full implementation, essentially doing it the same way you would do it if you were implementing it from scratch. For context, before looking at the code, keep in mind how the views are laid out:
https://github.com/android/platform_packages_apps_contacts/blob/lollipop-release/res/layout/quickcontact_activity.xml
The MultiShrinkScroller is a FrameLayout which intermediates the scrolling behavior, but the main stuff is in a LinearLayout, so reducing the height of the higher views will "scroll" the lower views upwards.
The key file for the implementation is this one:
https://github.com/android/platform_packages_apps_contacts/blob/lollipop-release/src/com/android/contacts/widget/MultiShrinkScroller.java
public void scrollTo(int x, int y) {
final int delta = y - getScroll();
boolean wasFullscreen = getScrollNeededToBeFullScreen() <= 0;
if (delta > 0) {
scrollUp(delta);
} else {
scrollDown(delta);
}
updatePhotoTintAndDropShadow();
updateHeaderTextSizeAndMargin();
//... other stuff
}
private void scrollUp(int delta) {
// Collapse higher views first
if (getTransparentViewHeight() != 0) {
final int originalValue = getTransparentViewHeight();
setTransparentViewHeight(getTransparentViewHeight() - delta);
setTransparentViewHeight(Math.max(0, getTransparentViewHeight()));
delta -= originalValue - getTransparentViewHeight();
}
// Shrink toolbar as needed
final ViewGroup.LayoutParams toolbarLayoutParams
= mToolbar.getLayoutParams();
if (toolbarLayoutParams.height > getFullyCompressedHeaderHeight()) {
final int originalValue = toolbarLayoutParams.height;
toolbarLayoutParams.height -= delta;
toolbarLayoutParams.height = Math.max(toolbarLayoutParams.height,
getFullyCompressedHeaderHeight());
mToolbar.setLayoutParams(toolbarLayoutParams);
delta -= originalValue - toolbarLayoutParams.height;
}
// Finally, scroll content if nothing left to shrink
mScrollView.scrollBy(0, delta);
}
updatePhotoTintAndDropShadow(); and updateHeaderTextSizeAndMargin(); handle the change in tint and text as it gets collapsed so that it turns into the look and feel of a regular ActionBar/ToolBar.
You could grab the MultiShrinkScroller file itself and adapt it for your own use, but there are probably easier implementations nowadays (including those from Android's design library).
I have a problem with mediacontroller which is hidden behind navigation bar (soft navigation keys on ICS). At first is OK (first picture), but when is navigation bar hidden for the first time, mediacontroller is resized to fit screen (correct), but is not resized back when navigation bar appears again (second picture). Also ad is moved behind (hidden for screenshot).
If I understand documentation correct fitsSystemWindows should be responsible for resizing. But it's not working.
How can I do that? Thanks for any help.
I'm testing this on Galaxy Nexus.
XML layout:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/playerLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:animateLayoutChanges="true"
android:background="#color/black" >
<mynamespace.BKDVideoView
android:id="#+id/videoview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
<mynamespace.SubtitleTextView
android:id="#+id/subtitleText"
style="#style/SubtitleOverlayText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="30dp"
android:gravity="center"
android:visibility="gone"
android:fitsSystemWindows="true"
android:animateLayoutChanges="true"/>
<FrameLayout
android:id="#+id/adLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|right"
android:fitsSystemWindows="true"
android:animateLayoutChanges="true"/>
<FrameLayout
android:id="#+id/videoMediaControllerHolder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:animateLayoutChanges="true"/>
BKDVideoView is copy from GrepCode of VideoView with some customizations. I did the same for MediaController.
In MediaController I'm calling hidding like that:
int newVis = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | SYSTEM_UI_FLAG_LAYOUT_STABLE;
if (!visible)
{
newVis |= SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION;
}
// mSystemUiHolder -> FrameLayout (playerLayout)
mSystemUiHolder.setSystemUiVisibility(newVis);
Update: In case you have the same problem please check also comment in accepted answer. For views that needs to be fullscreen use sammyboy code. Thanks to both. Sorry, that I need too much time to figure this out and couldn't give you points :(
this is systembar problem. Some devices fill_parent or match_parent entities has full screensizes and do not recognize systembar width and height.
I suggest that: programmatically give an integer value to views. (calculate system bar width and height). and remove sb's width or height (landscape or portrait mode) from screensize
and set this value to the views.
here the answer how to get screen dimensions etc.
Look at this:
http://bin-liu.blogspot.no/2012/03/how-to-hide-and-display-navigation-bar.html
public void onLayoutClicked(View v) {
view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
.
Display display = getWindowManager().getDefaultDisplay();
Method mGetRawH = Display.class.getMethod("getRawHeight");
Method mGetRawW = Display.class.getMethod("getRawWidth");
int rawWidth = (Integer) mGetRawW.invoke(display);
int rawHeight = (Integer) mGetRawH.invoke(display);
Use bringToFront() for the views to be at the top
Since VideoViews are SurfaceViews, they do not have the same behavior as a normal View. You need to ensure that it remains in the background by specifying:
videoview.setZOrderMediaOverlay(false);
add android:fitsSystemWindows="false" inside your framelayout that contain the surfaceview.
and this code inside your activity
your_framelayout_here.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);