Shrinking Tab Indicator (TabLayout) & Limits of it's Design Requirements - android

Here's a design requirement for our project, as far as I know the TabLayout is highly customisable but it has it's limitations.
So far I've tried the below:
<com.google.android.material.tabs.TabLayout
android:id="#+id/xxx"
android:layout_width="340dp"
android:layout_marginStart="44dp"
android:layout_height="12dp"
android:layout_alignBottom="#id/constraintLayout"
app:tabBackground="#drawable/tablayout_unselected"
app:tabGravity="center"
app:tabPadding="12dp"
app:tabContentStart="6dp"
app:tabPaddingTop="6dp"
app:tabIconTint="#color/black"
app:tabIndicator="#drawable/tablayout_selected"
app:tabIndicatorAnimationDuration="250"
app:tabIndicatorAnimationMode="elastic"
app:tabIndicatorColor="#color/carbon_black"
app:tabIndicatorFullWidth="false"
app:tabIndicatorGravity="stretch"
app:tabIndicatorHeight="6dp"
app:tabMinWidth="66dp"
app:tabMode="scrollable"
app:tabPaddingEnd="-28dp"
app:tabPaddingStart="-28dp"
app:tabRippleColor="#color/carbon_red_a700"
app:tabSelectedTextColor="#color/black"
app:tabTextColor="#android:color/black"
app:tabUnboundedRipple="true" />
Non-selected tab XML:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<gradient
android:angle="0"
android:startColor="#color/carbon_black_6"
android:endColor="#color/black"/>
<corners
android:radius="20dp"/>
<stroke
android:width="1dp"
android:color="#color/black"/>
</shape>
</item>
</selector>
Selected tab XML:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<gradient
android:angle="0"
android:startColor="#color/black"
android:endColor="#color/blinqDarkerRed"/>
<corners
android:radius="20dp"/>
</shape>
</item>
</selector>
below is how this looks and this is as close as I could get to the design:
Is it not possible to get this design 1:1 implemented ? Thanks !

Related

How can I set round ripple shape of TabLayout's ta?

I'm going to set round ripple shape of tablayout's tab. The TabLayout is linked to viewpager. I tried to define selector XML and set tabbackground attribute of tablayout with the selector xml.
So it has been set round. But the issue is that it works after I click it first. So that means the ripple of every tab doesn't work at the first click. What's the reason?
Thanks.
This is my code.
<com.google.android.material.tabs.TabLayout
android:id="#+id/unit_categories"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:theme="#style/Theme.AppCompat.Light.NoActionBar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tabBackground="#drawable/unit_category_selector_tab_background"
app:tabGravity="center"
app:tabIndicator="#drawable/unit_category_tab_indicator"
app:tabIndicatorFullWidth="true"
app:tabIndicatorGravity="center"
app:tabIndicatorHeight="40dp"
app:tabMode="scrollable"
app:tabRippleColor="#android:color/transparent"
app:tabUnboundedRipple="false" />
This is unit_category_selector_tab_background.xml
<?xml version="1.0" encoding="utf-8"?>
<item android:state_pressed="true" android:state_selected="false" android:drawable="#drawable/unit_category_tab_ripple"/>
</selector>
This is unit_category_tab_ripple.xml
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#9BB3B1">
<item>
<shape
android:shape="rectangle"
>
<solid android:color="#FFFEFE" />
<corners
android:radius="40dp" />
</shape>
</item>
</ripple>
<com.google.android.material.tabs.TabLayout
android:id="#+id/unit_categories"
android:layout_width="match_parent"
android:layout_height="#dimen/unit_category_tab_height"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:background="#android:color/transparent"
android:theme="#style/Theme.AppCompat.Light.NoActionBar"
app:tabGravity="center"
app:tabIndicator="#drawable/unit_category_tab_indicator"
app:tabIndicatorFullWidth="true"
app:tabIndicatorGravity="center"
app:tabIndicatorHeight="#dimen/unit_category_tab_height"
app:tabMode="scrollable"
app:tabRippleColor="#android:color/transparent"
app:tabTextColor="#color/unit_calc_text_color"
app:tabUnboundedRipple="false" />
tab_indicator.xml
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#D584D5">
<item>
<shape
android:shape="rectangle">
<!-- radius should be half of the desired TabLayout height -->
<corners
android:radius="#dimen/unit_category_tab_height"/>
<!-- color of the selected tab -->
<solid android:color="#android:color/transparent"/>
<stroke android:width="1dp" android:color="#color/tab_indicator_color"/>
</shape>
</item>
</ripple>
tab_background.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:enterFadeDuration="0" android:exitFadeDuration="1500">
<item android:state_pressed="true" android:state_selected="false" android:drawable="#drawable/unit_category_tab_ripple"/>
</selector>
I set background by the code when the tab changes
tab_riple.xml
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#C1DCD9">
<item>
<shape android:shape="rectangle">
<solid android:color="#color/calculator_primary_color" />
<corners android:radius="#dimen/unit_category_tab_height" />
<stroke android:width="2dp" android:color="#android:color/transparent"/>
</shape>
</item>
</ripple>

Android's elevation not working with different rounded-corners rectangle

EDIT: suggested solutions here offer me to draw the shadows myself. I
don't want that as the view will be animated (translationZ will change
over time) and I would like to avoid rendering the shadows myself
during the animation. I would like some solution to help
android-system recognize my shape as a background for the elevation.
If no such solution will be found, the hard way will be subclassing a
ViewOutlineProvider with convexPath, but I would really like to avoid
this.
As the name of the question suggests, I have a problem getting android's elevation to work with a rectangle of different rounded-corners. (pictures added at the end of the question)
It does work when there is only 1 default radius, i.e with this example:
rounded_rect.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#android:color/holo_orange_dark"/>
<corners android:radius="5dp"/>
</shape>
activity.xml
<?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:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:background="#drawable/rounded_rect"
android:elevation="5dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
But when I'm changing rounded_rect.xml to the following code, no shadows are being casted:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#android:color/holo_orange_dark"/>
<corners
android:bottomRightRadius="5dp"
android:bottomLeftRadius="20dp"
android:topLeftRadius="10dp"
android:topRightRadius="30dp"
/>
</shape>
I have tried adding also android:radius="5dp" into the <corners> tag in rounded_rect.xml , but it didn't add shadows.
Any help would be much appreciated!
picture working with default radius for all corners:
picture not working with different radius for each corner - no shadows:
Refer this
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Bottom 2dp Shadow -->
<item>
<shape android:shape="rectangle">
<solid android:color="#d8d8d8" />
<corners android:radius="7dp" />
</shape>
</item>
<!-- White Top color -->
<item android:bottom="3px">
<shape android:shape="rectangle">
<solid android:color="#FFFFFF" />
<corners android:radius="7dp" />
</shape>
</item>
</layer-list>
I got it to work using my custom subclass of ViewOutlineProvider . in my subclass I calculated a Path that its isConvex() returns true, and used that path as the shadow.
use this online making tool this will help you to make shapes
in that at border radius
Apply this code. Set the button as per your requirement
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<layer-list>
<item android:right="5dp" android:top="5dp">
<shape>
<corners android:topRightRadius="40dp"
android:bottomLeftRadius="10dp"
android:bottomRightRadius="10dp"
android:topLeftRadius="10dp"/>
<solid android:color="#D6D6D6" />
</shape>
</item>
<item android:bottom="2dp" android:left="2dp">
<shape>
<gradient android:angle="270"
android:endColor="#android:color/holo_orange_dark" android:startColor="#android:color/holo_orange_dark" />
<stroke android:width="1dp" android:color="#BABABA" />
<corners android:topRightRadius="40dp"
android:bottomLeftRadius="10dp"
android:bottomRightRadius="10dp"
android:topLeftRadius="10dp"/>
<padding android:bottom="10dp" android:left="10dp"
android:right="10dp" android:top="10dp" />
</shape>
</item>
</layer-list>
</item>
</selector>

How to show a circle tab indicator along Viewpager?

I want to show a tabindicator as in the image below.
I am using viewpager. I already tried TabLayout with viewpager, in which we can only adjust tab indicator color and height. How can I implement this.
when seleted 'tab_selected.xml'
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:shape="ring"
android:useLevel="false"
android:thickness="4dp"
android:innerRadius="0dp">
<solid android:color="#000"/>
</shape>
</item>
</selector>
when not selected 'tab_unselected'
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:shape="ring"
android:useLevel="false"
android:thickness="4dp"
android:innerRadius="0dp">
<solid android:color="#3b000000"/>
</shape>
</item>
</selector>
now when state_presses is true or not 'tab'
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/tab_selected"
android:state_selected="true"/>
<item android:drawable="#drawable/tab_unseleted"/>
</selector>
now in tablayout
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/tablayout"
android:layout_alignParentBottom="true"
app:tabIndicatorHeight="0dp"
app:tabGravity="center"
app:tabBackground="#drawable/tab"/>
Keep it simple and just use one XML file.
tab_indicator_circle.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="0dp"
android:shape="ring"
android:thickness="4dp"
android:useLevel="false">
<size
android:width="4dp"
android:height="4dp" />
<solid android:color="#color/colorAccent" />
</shape>
Usage:
<com.google.android.material.tabs.TabLayout
android:id="#+id/myTabLayout"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:tabIndicator="#drawable/tab_indicator_circle"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tabIndicatorHeight="10dp"
app:tabGravity="center" />
Note that I'm using TabLayout from
implementation "com.google.android.material:material:1.1.0-alpha10"
Here's how I achieved it
tab_indicator.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:width="8dp"
android:height="8dp"
android:bottom="16dp"
android:end="8dp"
android:gravity="center"
android:start="8dp"
android:top="8dp">
<shape android:shape="rectangle">
<size android:width="8dp" android:height="8dp" />
<corners android:radius="4dp" />
<solid android:color="?attr/colorAccent" />
</shape>
</item>
</layer-list>
Important thing is to have fixed width and height.
Usage:
<com.google.android.material.tabs.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIndicatorHeight="8dp"
app:tabIndicator="#drawable/tab_indicator" />

Set color to unselected tab indicator in tab layout

I am using tablayout provided by google and everything is working fine except the color of the unselected tab indicator. I am unable to set the unselected tab indicator color.
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"
style="#style/MyCustomTabLayout"
/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" /> </android.support.design.widget.CoordinatorLayout>
**1.app:**
tabBackground="#drawable/tablayout_selector"
**2.tablayout_selector.xml**
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#color/shl_common_default_color" />
</shape>
</item>
<item>
<inset android:insetBottom="1.5dp">
<shape android:shape="rectangle">
<solid android:color="#color/white" />
</shape>
</inset>
</item>
</layer-list>
or
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#color/white" />
</shape>
</item>
<item android:gravity="bottom">
<shape android:shape="rectangle">
<solid android:color="#color/shl_common_default_color" />
<size android:height="1.5dp" />
</shape>
</item>
</layer-list>
try this changing the color as you wish:
Create this file in drawable folder
tab_indicator_color.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- UNSELECTED TAB STATE -->
<item android:state_selected="false" android:state_pressed="false">
<layer-list>
<!-- Bottom indicator color for the UNSELECTED tab state -->
<item android:top="-5dp" android:left="-5dp" android:right="-5dp">
<shape android:shape="rectangle">
<stroke android:color="#65acee" android:width="2dp"/>
</shape>
</item>
</layer-list>
</item>
</selector>
and after set your .xml file in app:tabBackground like this:
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"
style="#style/MyCustomTabLayout"
app:tabBackground="#drawable/tab_indicator_color" />
ic_tab_indicator_default.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle" />
</item>
<item android:gravity="bottom">
<shape android:shape="rectangle">
<size android:height="1dp" />
<solid android:color="#color/steel_blue" />
</shape>
</item>
</layer-list>
ic_tab_indicator_selected.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle" />
</item>
<item android:gravity="bottom">
<shape android:shape="rectangle">
<size android:height="3dp" />
<solid android:color="#color/congress_blue" />
</shape>
</item>
</layer-list>
selector_tab_indicator.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/ic_tab_indicator_selected" android:state_selected="true" />
<item android:drawable="#drawable/ic_tab_indicator_default" />
</selector>
TabLayout
<com.google.android.material.tabs.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIndicator="#android:color/transparent"
app:tabBackground="#drawable/selector_tab_indicator">
For people using the new com.google.android.material.tabs.TabLayout if you apply the solution given as the correct answer in this post would get corners on all four sides of the tab
To fix that use the following "hack"
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- UNSELECTED TAB STATE -->
<item android:state_selected="false" android:state_pressed="false">
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Bottom indicator color for the UNSELECTED tab state -->
<item android:top="-10dp" android:left="-1000dp" android:right="-1000dp">
<shape android:shape="rectangle" >
<stroke android:color="#4cffffff" android:width="1dp"/>
</shape>
</item>
</layer-list>
</item>
</selector>
If your TabLayout don't need title, but need indicator for unselected color.
You can do like
<com.google.android.material.tabs.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="10dp"
app:tabBackground="#drawable/tab_normal"
app:tabIndicator="#drawable/tab_indicator"
app:tabIndicatorColor="#null"
app:tabIndicatorHeight="10dp" />
The workaround here is
Using both tabBackground and tabIndicator
Indicator height equals to TabLayout height
tab_normal.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#aaaaaa" />
<corners android:radius="5dp" />
</shape>
tab_indicator.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#ff0000" />
<corners android:radius="5dp" />
</shape>
If you need a padding between indicator, you can use layer-list drawable with some padding (instead of using shape)
If you just only need a color for tab indicator, no need to define shape drawable, can use
app:tabBackground="#color/gray"
app:tabIndicatorColor="#color/red"

Custom thumb for a seekbar in Android

I want to create a custom thumb for seekbar that should look like this:
One solution could be this one, where png pictures are used to draw the thumb.
I believe that it should be possible to use xml only, since it is very similar to this thumb:
thumb.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size android:height="30dp" android:width="30dp"/>
<stroke android:width="18dp" android:color="#882EA5DE"/>
<solid android:color="#2EA5DE" />
<corners android:radius="1dp" />
</shape>
Just need to add second border (white stroke around), so that I can skip to manage all that pictures for different screen resolutions (hdpi/mdpi/xhdpi/xxhdpi).
I have tried different combination with shapes "oval" and "ring", but could not get the result required. How can you make it?
I could not manage to find a solution with just xml, that is why I used a picture to solve this, with a little help from this answer:
Created an image of the thumb seekbar_thumb_icon.png and saved it in different resolutions in res/drawable-* maps (hdpi/mdpi/xhdpi/xxhdpi).
Specified "android:thumb="#layout/seekbar_thumb" for SeekBar:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<item>
<shape>
<size
android:height="30dp"
android:width="30dp" />
<solid android:color="#android:color/transparent" />
</shape>
</item>
<item android:drawable="#drawable/balance_icon_48px"/>
</layer-list>
Other styles:
<SeekBar
android:id="#+id/seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progressDrawable="#layout/seekbar_style"
android:thumb="#layout/seekbar_thumb" />
seekbar_style.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="match_parent"
android:layout_width="match_parent">
<item android:id="#android:id/background"
android:drawable="#layout/seekbar_background" />
<item android:id="#android:id/progress">
<clip android:drawable="#layout/seekbar_progress" />
</item>
</layer-list>
seekbar_background.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:shape="line">
<stroke android:width="2dp" android:color="#868686"/>
<corners android:radius="1dp" />
</shape>
seekbar_progress.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:shape="line">
<stroke android:width="2dp" android:color="#ffffff"/>
<corners android:radius="1dp" />
</shape>

Categories

Resources