I would like to get the background of the tab animated smoothly to the selected position (just like the default tabIndicator animates between tabs).
Here is how my TabLayout looks like
<android.support.design.widget.TabLayout
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/tabLayout"
app:tabBackground="#drawable/tab_selector"
app:tabTextColor="#color/white"
android:background="#drawable/tab_layout_bg"
app:tabTextAppearance="#android:style/TextAppearance.Widget.TabWidget"
app:tabIndicator="#null"
app:tabRippleColor="#null">
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/tab1"/>
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/tab2"/>
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/tab3"/>
</android.support.design.widget.TabLayout>
Here, Tab 3 is selected. If i select Tab 1 the background should animate from Tab 3 to Tab 1.
I am using selector to change the background of the tabs.
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_selected="true"
android:drawable="#drawable/tab_layout_fg"/>
<item
android:drawable="#drawable/tab_layout_bg"/>
</selector>
Here i am attaching the sample animation. See just the tab bar.
Is it possible to achieve this kind of animation with approach i am following? If not please suggest me another way. I have been working on this from two days. Still can't figure it out.
Thanks in advance.
We've achieved the same effect in our app using TabLayout.
The trick for smooth animation is to use tabIndicator attirbute instead of tabBackground!
You can define a shape drawable (not selector) and assign it to TabLayout by:
app:tabIndicator="#drawable/tab_layout_fg"
This will add a tab indicator with smooth animation that you want to achieve.
If you find that tabIndicator color is not reflecting as defined in the drawable file, you can tint the tabIndicator using tabIndicatorColor attribute.
Note: Make sure you're using latest design support library v28.0.0 or material components library for Android X.
Check the #Maulik answer. It is what you are looking for.
Just to integrate the answer, without a custom shape (in your example you are using it) you can just use:
<com.google.android.material.tabs.TabLayout
app:tabIndicatorGravity="stretch"
app:tabIndicatorColor="#color/...."
..>
The INDICATOR_GRAVITY_STRETCH allows you to stretch the tab selection indicator across the entire height and width. In this way you can just use the app:tabIndicatorColor without drawable to set the selected color used.
The animation is provided by default.
Related
First of all, I am sorry to ask a question like this but after I downloaded latest Google IO app,
I am just loving the bottom Layout as shown in the following
screenshot
Being new to android development, I have no clue where to start, Any idea how to achieve this bottom Layout with circle star in XML? Does anyone know what this design is called?
You can use the new Material Components for Android and the BottomAppBar component.
Use something like:
<com.google.android.material.bottomappbar.BottomAppBar
android:id="#+id/bar"
android:layout_gravity="bottom"
app:fabCradleMargin="8dp"
app:fabCradleRoundedCornerRadius="8dp"
app:fabCradleVerticalOffset="0dp"
... />
<com.google.android.material.floatingactionbutton.FloatingActionButton
app:layout_anchor="#id/bar"
../>
You have to use these attributes:
fabCradleMargin attribute.
It increases or decreases the distance between the FloatingActionButton and the BottomAppBar
fabCradleRoundedCornerRadius attribute. It specifies the roundness of the corner around the cutout
OLD SUPPORT LIBRARY
With the Support Library 28.0.0, the Design Library contains the BottomAppBar.
You can use
<android.support.design.bottomappbar.BottomAppBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:backgroundTint="#color/colorPrimary"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
You can customize the component using these attributes:
app:fabAlignmentMode: Declares the position of the FAB which has been attached to the bottom app bar. This can be either end or center
app:fabCradleVerticalOffset: Declares the vertical offset to be used for the attached fab. By default this is 0dp.
app:backgroundTint: Used to apply a tint to the background of the view.
Also you you can attach a fab by using app:layout_anchor on the FAB component which you wish to attach, using the ID of the bottom app bar.
I believe it's the BottomAppBar, coming in support library 28.0.0. You can read more here: https://medium.com/#lupajz/the-place-for-bottomappbar-31e0db8f70b1
App bars: bottom
Bottom app bars provide access to a bottom navigation drawer and up to four actions, including the floating action button.
Bottom app bars can contain actions that apply to the context of the current screen. They include a navigation menu control on the far left and a floating action button (when one is present). If included in a bottom app bar, an overflow menu control is placed at the end of other actions.
Informações enter link description here
<android.support.design.widget.FloatingActionButton
android:id="#+id/FloatingActionButtonAddEmp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
app:srcCompat="#drawable/ic_save_black_24px"
app:layout_anchor="#+id/bottom_appbar"/>
<android.support.design.bottomappbar.BottomAppBar
android:id="#+id/bottom_appbar"
android:elevation="4dp"
style="#style/Widget.MaterialComponents.BottomAppBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:fabAttached="true"
app:backgroundTint="#color/io15_grey"/>
The TabLayout documentation gives an example of nesting TabItem directly inside TabLayout like so:
<android.support.design.widget.TabLayout
android:layout_height="wrap_content"
android:layout_width="match_parent">
<android.support.design.widget.TabItem
android:text="#string/tab_text"/>
<android.support.design.widget.TabItem
android:icon="#drawable/ic_android"/>
</android.support.design.widget.TabLayout>
But it gives no example of how this could be used in practice, and the documentation for TabItem says:
This view is not actually added to TabLayout, it is just a dummy which allows setting of a tab items's text, icon and custom layout.
So what is TabItem for? After extensive Googling, I cannot find a single example of anyone defining TabItems in XML. Is there any way to set up a tabbed activity using TabItem in the resource file as shown above?
This appears to be a relatively recent addition to the design library, apparently added in version 23.2.0, though it's not mentioned in the revision history. It's functionality is pretty basic, and the only attributes it seems to use are the three given in its docs: text, icon, and layout.
From testing, it seems it's basically an XML shortcut for creating a new Tab, and setting its text, icon, and custom View, as one would usually do in code. When it says "This view is not actually added to TabLayout", I believe it's meant to suggest that it's not a View in the regular sense, in that you can't set any kind of standard layout attribute on it, like layout_width or background. It simply serves to cause the TabLayout to create a new Tab for each TabItem, and call setText(), setIcon(), and setCustomView() accordingly.
For example, to add a Tab in code, we would usually do something like this:
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
// Add Tab
TabLayout.Tab tab = tabLayout.newTab();
tab.setCustomView(R.layout.tab);
tab.setText("Tab 1");
tab.setIcon(R.drawable.ic_launcher);
tabLayout.addTab(tab);
Whereas now we can replace everything after the comment above by adding a TabItem in the layout.
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TabItem
android:layout="#layout/tab"
android:text="Tab 1"
android:icon="#drawable/ic_launcher" />
</android.support.design.widget.TabLayout>
Do note that the same requirements for the custom View layout still apply. That is, the TextView for the text must have the system Resource ID #android:id/text1, and the ImageView for the icon must have the ID #android:id/icon. As an example, the R.layout.tab from above:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<ImageView android:id="#android:id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView android:id="#android:id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Quick addition to #Mikes very helpful answer:
Android Studio now has a Template on how to use a TabLayout with TabItem setup in an XML layout. Create all needed files with "New > Activity > Tabbed Activity" and choose "Action Bar Tabs(with ViewPager)" as shown in the screenshot:
If you want to adjust the look of the TabItem without a custom view: use white vector assets as tab android:icon and tint them with a selector (providing different colors based on android:state_selected)
The color of the line under the currently selected tab is set as app:tabIndicatorColor on tag TabLayout.
It took me a while to get it to work, so the complete steps turned into such a long answer that I don't want to copy them here. You can find my more detailed answer with full code at:
https://stackoverflow.com/a/49603559/414581
please see com.google.android.material.tabs.TabItem class it accepts icon text from attributes, but seems like you will need to add Tags on runtime.
I am using Google's new TabLayout from design support library and was wondering how can I center active tab inside that layout.
Currently I am centering whole layout like this:
<android.support.design.widget.TabLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
And now I would like to center active tab inside of that layout. Something like how it was done before TabLayout. No matter how many tabs were there, active one was always in center. How can I accomplish that? Thank you.
Need to use padding for SlidingTabStrip
Look here: https://stackoverflow.com/a/36886331/651770
I added a ripple effect on a ImageButton, however it is hidden by an ImageView used as a background for the parent view RelativeLayout.
Here's the layout file:
<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="172dp"
android:orientation="vertical"
android:theme="#style/ThemeOverlay.AppCompat.Dark">
<ImageView
android:id="#+id/drawerBackgroundImageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="#drawable/drawer_background"/>
[...]
<ImageButton
android:id="#+id/drawerLogoutButton"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_alignBottom="#id/drawerEmailTextView"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginEnd="#dimen/activity_horizontal_margin"
android:layout_marginRight="#dimen/activity_horizontal_margin"
style="#style/FlatButtonStyle"
android:scaleType="centerInside"
android:src="#drawable/ic_logout_white_24dp"/>
</RelativeLayout>
(there's a bunch of other views but they're irrelevant here)
I'm using an ImageView as the background for the RelativeLayout as I need to set a specific scaleType for the image, so I can't use the basic android:background property.
The ripple effect is hidden as it doesn't have a mask layer (I want it to extend out of the button's bounds) and thus uses the ImageButton's parent view to be displayed. The effect is perfectly visible if I remove the ImageView.
Is there a way to get the ripple effect to be shown above the problematic ImageView?
I had exactly the same issue and solved it using this thread: https://code.google.com/p/android/issues/detail?id=155880
Issue preview:
Before solved:
After solved:
Explanation:
"Borderless buttons draw their content on the closest background. Your button might not be having background between itself and the ImageView, so it draws underneath the ImageView."
Solution:
"Use a transparent background (android:background="#android:color/transparent") on some layout containing the button (beneath the ImageView). This will dictate what the maximum bounds of the ripple effect is."
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
...>
<!-- Your background ImageView -->
<ImageView
android:id="#+id/drawerBackgroundImageView"
android:src="#drawable/drawer_background"
... />
<!-- ... -->
<!-- HERE, you need a container for the button with the transparent
background. Let's say you'll use a FrameLayout -->
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/transparent">
<!-- Maybe more items -->
<!-- Button with borderless ripple effect -->
<ImageButton
android:id="#+id/drawerLogoutButton"
android:background="?selectableItemBackgroundBorderless"
... />
</FrameLayout>
</FrameLayout>
Hope it helps.
I am experiencing same issue. Only solution I have found so far is not 100% okay since ripple is masked by view (its not borderless).
The solution (workaround):
surround your ImageButton with other view and set ripple to the foreground instead of the background in your layout like this:
<ImageView ... />
<FrameLayout
...
android:clickable="true"
android:focusable="true"
android:foreground="?attr/selectableItemBackgroundBorderless" >
<ImageButton />
</FrameLayout>
I would be really glad if someone explain why the ripple is drawn behind the image. Also if you look at Google Photos app, in image detail they have transparent icons over image view with ripple. I would like to replicate this, but I am not able to make the ripple to be in foreground. Does anybody know how to put transparent imagebuttons over everything but still have the ripple?
EDIT final solution
here you can find exactly same question link
with great explanation what is happening. the solution is the same but on top of that it solves rectangular mask by adding
android:clipChildren="false"
android:clipToPadding="false"
to your layout. now your ripple should be borderless (it worked for me).
The layout xml could be something like this:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
android:clipChildren="false"
android:clipToPadding="false">
<ImageView ... />
<FrameLayout
...
android:clickable="true"
android:foreground="?attr/selectableItemBackgroundBorderless">
<ImageView ... />
</FrameLayout>
</FrameLayout>
I'm aware this is an old post but I did struggle with this quite a bit today hence I'm posting what I was finally able to figure out and maybe someone else might benefit from it. One key emphasis beforehand, please do always RTFM!
1) The story
I aimed to use the unbounded ripple effect on Tab Items and consequently have it spread all over the AppBarLayout area. I had applied #android:color/transparent to TabLayout as the first wrapping parent and gave AppBarLayout a background color, nevertheless the ripple was still being cut off right at the borders of TabLayout's height.
2) The moral of the story (RTFM)
So I run to the nest of Android knowledge: The Documentation, and spotted this:
?android:attr/selectableItemBackgroundBorderless for a ripple that extends beyond the view. It will be drawn upon, and bounded by, the nearest parent of the view with a non-null background.
3) The course of action
Using Layout Inspector, I realized that #android:color/transparent although transparent (duh!) it actually assigns 0 as the value of the bg attribute of a View, but zero is not null hence the ripple gets bounded at the nearest parent.
4) The conclusion
With that in hand, I went and set the android:background property of my TabLayout to #null rather than transparent, and now I have a fancy little ripple spread onto the area of the AppBarLayout.
5) Outro: **ANDROID & SO FTW!
Props to everyone in this post who shed light on the matter in word. Cheers!
After wrapping ImageButton inside FrameLayout, I was getting rectangular shape on touch. Applied background with oval shape on FrameLayout and got the circular shape on touch.
Had the same issue. Used the solutions described above and worked. Managed to avoid the wrapping FrameLayout by setting foreground as ?attr/actionBarItemBackground and background as #null.
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|end"
android:background="#null"
android:contentDescription="#string/app_name"
android:foreground="?attr/actionBarItemBackground"
android:padding="#dimen/small_margin"
android:src="#drawable/ic_clear_text_icon" />
I'm trying to use Etsy's Staggered Gridview (https://github.com/maurycyw/StaggeredGridView), and I have it working mostly as expected, except I'm having an issue trying to get the selector to draw on top.
I've tried using mGridView.setDrawSelectorOnTop( true ); and android:drawSelectorOnTop="true" in the layout, but no success yet. Anyone happen to have solved this problem, or know if it's not possible with the library in its current state?
Etsy's StaggeredGrid frustratingly doesn't support item selector drawables. To work around this, set the selector on the GridView item, not the GridView itself.
In my current project, I wrap the GridView item in a FrameLayout, because a FrameLayout has an android:foreground attribute:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:foreground="?android:attr/selectableItemBackground">
<!-- Your item layout goes here. -->
</FrameLayout>
?android:attr/selectableItemBackground gives you the standard blue highlight. If you want, you can use your own state list drawable instead.