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" />
Related
I need to do a custom tab indicator for my tab layout. It will be linked to a ViewPager with a TabLayoutMediator. The layout that I need is this:
And I am currently getting this:
Anyone knows why? You can see my XML code below.
Layout where TabLayout is:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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"
android:background="#color/whiteCandy"
android:fitsSystemWindows="true">
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/onBoardingViewPager"
android:layout_width="match_parent"
android:layout_height="#dimen/dimen_0"
android:layout_marginStart="#dimen/tablet_default_margin"
android:layout_marginTop="#dimen/dimen_40"
android:layout_marginEnd="#dimen/tablet_default_margin"
android:layout_marginBottom="#dimen/dimen_75"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.tabs.TabLayout
android:id="#+id/tabDots"
android:layout_width="wrap_content"
android:layout_height="#dimen/dimen_6"
android:layout_marginStart="#dimen/dimen_30"
android:layout_marginBottom="#dimen/dimen_75"
android:background="#android:color/transparent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="#id/onBoardingViewPager"
app:tabBackground="#drawable/tab_selector"
app:tabIndicatorHeight="#dimen/dimen_0"
app:tabPaddingEnd="#dimen/dimen_6" />
</androidx.constraintlayout.widget.ConstraintLayout>
Tab Selector:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/selected_dot" android:state_selected="true" />
<item android:drawable="#drawable/default_dot" />
</selector>
Selected state drawable:
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="#dimen/dimen_3"/>
<solid android:color="#FFFF0000"/>
<size android:height="#dimen/dimen_6" android:width="#dimen/dimen_20"/>
</shape>
Unselected state drawable:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="#dimen/dimen_0"
android:shape="ring"
android:thickness="#dimen/dimen_6"
android:useLevel="false">
<solid android:color="#80FF0000" />
</shape>
</item>
</layer-list>
for unselected:
<shape android:shape="oval">
<solid android:color="#80FF0000" />
<size
android:width="4dp"
android:height="4dp" />
</shape>
I am trying to assign a custom Drawable to my Tablayout. The Problem is that when I do this, the Tablayout becomes invisible on my Samsung Galaxy S7. No problem at Nexus 5X.
Tablayout
<com.google.android.material.tabs.TabLayout
android:id="#+id/tl_shop_item"
style="#style/ShapeAppearanceOverlay.RSB3000.ShopTablayout"
android:layout_width="0dp"
android:layout_height="16dp"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toEndOf="#+id/vp_product"
app:layout_constraintStart_toStartOf="#+id/vp_product"
app:layout_constraintTop_toBottomOf="#id/vp_product"
app:tabIndicator="#drawable/shop_item_tab" <!-- THIS IS THE PROBLEM -->
app:tabIndicatorFullWidth="false"
app:tabIndicatorGravity="top"
app:tabMaxWidth="16dp" />
Drawable
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#color/blue"/>
<corners android:radius="5dp"/>
</shape>
OK, I found a fix:
Tablayout
<com.google.android.material.tabs.TabLayout
android:id="#+id/tl_shop_item"
style="#style/ShapeAppearanceOverlay.RSB3000.ShopTablayout"
android:layout_width="0dp"
android:layout_height="16dp"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toEndOf="#+id/vp_product"
app:layout_constraintStart_toStartOf="#+id/vp_product"
app:layout_constraintTop_toBottomOf="#id/vp_product"
app:tabBackground="#drawable/unselected_shop_item_tab"
app:tabIndicator="#drawable/selected_shop_item_tab"
app:tabIndicatorColor="#color/primary"
app:tabIndicatorGravity="center"
app:tabIndicatorFullWidth="false"
app:tabIndicatorHeight="8dp"
app:tabMaxWidth="16dp" />
Drawable: Selected_Shop_Item_Tab
<?xml version="1.0" encoding="utf-8"?>
<shape android:innerRadius="0dp"
android:shape="ring"
android:thickness="3dp"
android:useLevel="false"
xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/blue" />
</shape>
Drawable: Unselected_Shop_Item_Tab
<?xml version="1.0" encoding="utf-8"?>
<shape android:innerRadius="0dp"
android:shape="ring"
android:thickness="3dp"
android:useLevel="false"
xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/grey_light" />
</shape>
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>
I try to create half circle background, in development IDE preview it works, but when I launch in emulator it doesn't work.
Here is my shape code :
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:height="50dp">
<shape>
<solid android:color="#color/colorAccentDark" />
</shape>
</item>
<item android:top="-500dp" android:bottom="0dp" android:left="-100dp" android:right="-100dp">
<shape>
<corners android:radius="500dp" />
<solid android:color="#color/colorAccentDark" />
</shape>
</item>
</layer-list>
And here is my layout code :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/background_profile"
android:layout_weight="1">
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/profile_avatar"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="#drawable/ic_default_avatar"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"/>
<TextView
android:id="#+id/profile_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="#id/profile_avatar"
android:layout_marginTop="20dp"
android:textColor="#color/neutralWhite"
android:textStyle="bold"
android:textSize="18sp"
android:text="Avatar Ang"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="4.04">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello Android!"/>
</RelativeLayout>
</LinearLayout>
Maybe any other tweak to handle that?
Thank you
you can try this :
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#900021df"/>
<size
android:width="10dp"
android:height="5dp"/>
<corners
android:bottomLeftRadius="20dp"
android:bottomRightRadius="20dp"/>
</shape>
it gives this shape:
curve_toolbar_bg.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:bottom="0dp"
android:left="-100dp"
android:right="-100dp"
android:top="-80dp">
<shape android:shape="oval">
<solid android:color="#color/colorPrimary" />
</shape>
</item>
</layer-list>
activity_main.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"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="0dp"
android:layout_height="?android:attr/actionBarSize"
android:background="#drawable/rounded_corner"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0">
</android.support.v7.widget.Toolbar>
</android.support.constraint.ConstraintLayout>
You cannot create a semicircle from xml. but you could achieve what you are looking for using a circle with appropriate margin & padding.
You can use a circle shape .xml file.
Create a fixed sized circle like this:
Example:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval"
android:useLevel="false" >
<solid android:color="#006AC5" />
<size
android:height="50dp"
android:width="50dp" />
</shape>
Try this. Remove the gradient part then it will look like same as you want.
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#00B0EA" />
</shape>
</item>
<item
android:bottom="400dp"
android:left="-100dp"
android:right="-100dp"
android:top="-200dp">
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<gradient
android:angle="90"
android:endColor="#65FFFFFF"
android:startColor="#65FFFFFF" />
</shape>
</item>
<item
android:bottom="402dp"
android:left="-100dp"
android:right="-100dp"
android:top="-280dp">
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#FFFFFF" />
</shape>
</item>
Background.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FFFFFF" />
</shape>
</item>
<item
android:bottom="410dp"
android:left="-100dp"
android:right="-100dp"
android:top="-300dp">
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#7181A1" />
</shape>
</item>
</layer-list>
Output like
You can try to use ShapeOfView.
<io.github.florent37.shapeofview.shapes.ArcView
android:layout_width="match_parent"
android:layout_height="300dp"
android:elevation="4dp"
app:shape_arc_height="20dp"
app:shape_arc_position="bottom">
<!-- YOUR CONTENT -->
</io.github.florent37.shapeofview.shapes.ArcView>
Image result
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"