本篇是通过自定义系统自带的material
库里面的TabLayout
来实现上图效果。
通过分析,可以分为以下几个步骤:
整体效果用 xml
的 layer-list
来绘制。
整体背景是一个圆角矩形,一个正方形旋转45度角,放置底部,正方形上面部分与圆角矩形重叠,颜色设置成一致就能达到倒三角的效果。
在 drawable
文件夹中创建一个 layer_indicator.xml
文件
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<solid android:color="@color/blue"/>
<corners android:radius="8dp"/>
shape>
item>
layer-list>
item
不指定宽高,默认充满被设置View
,因为不能确定TabLayout
的Tab
的宽高,因此不设置 width
和height
属性。
其实就是绘制一个旋转45度的正方向。
<item android:width="10dp" android:height="10dp" android:bottom="2dp"
android:gravity="bottom|center_horizontal">
<rotate android:fromDegress="45"
android:pivotX="50%"
android:pivotY="50%">
<shape android:shape="rectangle">
<solid android:color="@color/red"/>
shape>
rotate>
item>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:bottom="5dp"> // 1.
<shape
android:layout_height="match_parent"
android:shape="rectangle">
<solid android:color="@android:color/holo_blue_light" />
<corners android:radius="8dp" />
shape>
item>
<item
android:width="10dp"
android:height="10dp"
android:bottom="2dp"
android:gravity="bottom|center_horizontal"> // 2.
<shape android:shape="rectangle">
<solid android:color="@android:color/holo_red_light" />
shape>
rotate>
item>
layer-list>
代码解释:
android:bottom="5dp"
设置圆角矩形距离底部5dp,否则矩形底部与正方形底部重合就看不到倒三角的效果了。
android:gravity="bottom|center_horizontal"
正方形放置在底部,并且水平居中。
android:fromDegrees="45"
旋转的起始角度
android:pivotX="50%" android:pivotY="50%"
设置正方形的旋转中心为正中心。默认旋转就是正方形中心,可以不设置。
app:tabIndicator="@drawable/layer_indicator"
设置Indicator,进行绘制.
来看下效果图
并没有达到我们想要的效果,这是因为indicator
的默认位置(app:tabIndicatorGravity="bottom"
)在底部,所以绘制图形的时候只在底部绘制。
app:tabIndicatorGravity
有4个属性:
可以看出,stretch 满足需求。
app:tabIndicatorGravity="stretch"
到这里,大致的功能基本上已经实现了,剩下的只有一些细节上的调整了。
app:tabIndicatorFullWidth="true"
: 指示器是否填充宽度
app:tabMode="scrollable"
: 模式 => scrollable 可滚动 | fixed => 固定屏幕宽度,超出屏幕宽度会压缩 | auto => 自动,在tab数量少的时候能看出区别
为了效果对比明显,使用2个Tab来演示。
app:tabIndicatorColor="@color/colorAccent"
: 设置指示器的背景色,同时设置tabIndicatorColor 和 layer_indicator.xml的颜色,以前者设置的为准
app:tabPaddingStart app:tabPaddingTop a:tabPaddingEnd app:tabPaddingBottom
: 设置Tab上下左右内边距
app:tabUnboundedRipple
: 无边界水波纹,当设置false时,水波纹有边界,为Tab所在的矩形边界
app:tabIndicatorColor="@color/colorAccent"
: 设置指示器的背景色
app:tabPaddingStart / app:tabPaddingTop / a:tabPaddingEnd / app:tabPaddingBottom
: 设置Tab上下左右内边距
layer_indicator.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:bottom="5dp">
<shape
android:layout_height="match_parent"
android:shape="rectangle">
<solid android:color="@android:color/holo_blue_light" />
<corners android:radius="8dp" />
shape>
item>
<item
android:width="10dp"
android:height="10dp"
android:bottom="2dp"
android:gravity="center_horizontal|bottom">
<rotate
android:fromDegrees="45"
android:pivotX="50%"
android:pivotY="50%">
<shape android:shape="rectangle">
<solid android:color="@android:color/holo_red_light" />
shape>
rotate>
item>
layer-list>
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:elevation="5dp"
android:paddingStart="10dp"
android:paddingTop="5dp"
android:paddingEnd="10dp"
app:tabIndicatorGravity="stretch"
app:tabIndicatorFullWidth="true"
app:tabIndicator="@drawable/layer_indicator"
app:tabIndicatorColor="@color/colorAccent"
app:tabUnboundedRipple="true"
app:tabMode="auto" />
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
LinearLayout>
学会了上面的自定义,那我们就可以做出下面的效果了(忘记在哪个APP里面看到过这个效果了!!!)
layer.xml
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:elevation="5dp"
android:paddingStart="10dp"
android:paddingTop="5dp"
android:paddingEnd="10dp"
app:tabIndicator="@drawable/layer"
app:tabIndicatorColor="@android:color/holo_orange_light"
app:tabIndicatorFullWidth="false"
app:tabIndicatorGravity="center"
app:tabMode="auto"
app:tabUnboundedRipple="true" />
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:elevation="5dp"
android:paddingStart="10dp"
android:paddingTop="5dp"
android:paddingEnd="10dp"
app:tabIndicator="@drawable/layer"
app:tabIndicatorColor="@android:color/holo_orange_light"
app:tabIndicatorFullWidth="false"
app:tabIndicatorGravity="center"
app:tabMode="auto"
app:tabUnboundedRipple="true" />
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
LinearLayout>