中间凹陷的BottomNavigationView(仿百度地图)

GapBottomNavigtionView

百度的:


71529789c6c948803e1075c2c7e00809.jpg

我的:


e9347423eb2031228af77ad63d7b01d7.jpg

项目地址:https://github.com/ZYF99/UIKit/tree/1.3

使用方式

在app的build.gradle中

allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }

    dependencies {
            implementation 'com.github.ZYF99:UIKit:1.3'
    }

在布局文件中直接使用

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab_add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="30dp"
        android:backgroundTint="#ffffff"
        android:elevation="6dp"
        android:src="@android:drawable/ic_input_add"
        android:tint="#000000"
        app:borderWidth="0dp"
        app:fabSize="normal"
        app:layout_constraintBottom_toBottomOf="@+id/bottomnavigation"
        app:layout_constraintEnd_toEndOf="@+id/bottomnavigation"
        app:layout_constraintStart_toStartOf="@+id/bottomnavigation"
        app:rippleColor="#00FFFFFF"/>

    <com.zhangyf.gapbottomnavigationview.GapBottomNavigationView
        android:id="@+id/bottomnavigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="32dp"
        android:layout_marginEnd="32dp"
        android:layout_marginBottom="16dp"
        android:backgroundTint="#ffffff"
        android:clickable="false"
        android:padding="8dp"
        app:center_radius="32dp"
        app:corner_radius="12dp"
        app:elevation="5dp"
        app:itemBackground="@null"
        app:itemIconTint="#000000"
        app:itemTextColor="#000000"
        app:labelVisibilityMode="labeled"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:menu="@menu/navigation"
        app:shadow_length="4dp"
        tools:targetApi="lollipop" />
  • app:center_radius: 用来指定凹陷的半径
  • shadow_length:用来指定高度(阴影大小)
  • cornerRadius:用来指定拐角处的平滑半径大小

源码

attrs中的3个属性

<?xml version="1.0" encoding="utf-8"?>
<resources>
        <declare-styleable name="GapBottomNavigationView">
            <attr name="shadow_length" format="dimension" />
            <attr name="corner_radius" format="dimension" />
            <attr name="center_radius" format="dimension" />
        </declare-styleable>
</resources>
导入源码(请直接copy)

源码采用Kotlin,有需要可以直接转为Java,转换方法自行百度

package com.zhangyf.gapbottomnavigationview

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.graphics.drawable.GradientDrawable
import android.os.Build
import android.util.AttributeSet
import android.util.Log
import androidx.annotation.*
import com.google.android.material.bottomnavigation.BottomNavigationView

class GapBottomNavigationView : BottomNavigationView {

    private var fabId = 0 //凹陷View的id
    private var centerRadius: Float = 0.toFloat() //中间凹陷的半径
    private var cornerRadius = 12f //拐角处的圆滑大小(越大越平滑)
    private var shadowLength = 6f //阴影大小

    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {
        background = GradientDrawable().apply { setColor(Color.TRANSPARENT) }
        val ta = context.obtainStyledAttributes(attrs, R.styleable.GapBottomNavigationView)
        centerRadius = ta.getDimension(R.styleable.GapBottomNavigationView_center_radius, 0.toFloat())
        shadowLength = ta.getDimension(R.styleable.GapBottomNavigationView_shadow_length, 6.toFloat())
        cornerRadius = ta.getDimension(R.styleable.GapBottomNavigationView_corner_radius, 12.toFloat())
        ta.recycle()
    }

    @SuppressLint("DrawAllocation")
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        val paint = Paint()
        val path = Path()

        //左边的半圆
        val rectL = RectF(
            shadowLength,
            shadowLength,
            height.toFloat() + shadowLength,
            height.toFloat() - shadowLength
        )
        path.arcTo(rectL, 90.toFloat(), 180.toFloat(), false)

        path.lineTo(width / 2 - centerRadius - cornerRadius, shadowLength)

        //左边转角处
        path.quadTo(
            width / 2 - centerRadius,
            shadowLength,
            width / 2 - centerRadius,
            cornerRadius + shadowLength
        )

        //中间凹陷的半圆
        val rectCenter = RectF(
            width / 2 - centerRadius,
            cornerRadius + shadowLength - centerRadius,
            width / 2 + centerRadius,
            cornerRadius + centerRadius + shadowLength
        )

        path.arcTo(rectCenter, 180.toFloat(), (-180).toFloat(), false)


        //利用贝塞尔曲线画中间凹陷(非半圆)
/*      path.quadTo(
            width.toFloat() / 2,
            centerRadius.toFloat(),
            width / 2 + centerRadius - cornerRadius - cornerRadius / sqrt(2.toFloat()),
            cornerRadius / sqrt(2.toFloat())
        )*/

        //右边转角处
        path.quadTo(
            width / 2 + centerRadius,
            shadowLength,
            width / 2 + centerRadius + cornerRadius,
            shadowLength
        )
        path.lineTo((width - shadowLength - height / 2), shadowLength)


        //右边的半圆
        val rectR = RectF(
            width.toFloat() - shadowLength - height,
            shadowLength,
            width.toFloat() - shadowLength,
            height.toFloat() - shadowLength
        )
        path.arcTo(rectR, 270.toFloat(), 180.toFloat(), false)

        //最后的直线
        path.moveTo((width - shadowLength - height / 2), height.toFloat() - shadowLength)
        path.lineTo(height / 2.toFloat() + shadowLength, height.toFloat() - shadowLength)
        path.close()
        Log.d("!!!", "!!!!!!!!!!!!")

        //按背景色填充背景
        paint.apply {
            style = Paint.Style.FILL
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                color = backgroundTintList?.defaultColor ?: Color.BLACK
            }
            maskFilter = null
            isAntiAlias = true
            //添加阴影
            setShadowLayer(shadowLength, 0.toFloat(), 0.toFloat(), Color.LTGRAY)
        }
        canvas.drawPath(path, paint)
    }
}

建议:结合我的代码并利用 paint(画笔) 随意更改为你想要的形状

我的效果就是这样咯


093143d5ebb666338bc164a6bd339da5.jpg

喜欢不要忘了点赞关注或者去github点个星星哦~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,165评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,720评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,849评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,245评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,596评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,747评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,977评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,708评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,448评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,657评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,141评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,493评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,153评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,890评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,799评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,685评论 2 272