仿百度地图的凹陷BottomNavigationView
2019-12-10 本文已影响0人
ZEKI安卓学弟
百度的:
71529789c6c948803e1075c2c7e00809.jpg
我的:
e9347423eb2031228af77ad63d7b01d7.jpg
使用
首先需要在attrs中申明两个属性
<resources>
<declare-styleable name="GapBottomNavigationView">
<attr name="anchor_fab" format="reference" />
<attr name="shadow_length" format="float" />
<attr name="corner_radius" format="float" />
</declare-styleable>
</resources>
anchor_fab: 用来指定凹陷下去的 View ,一般都为 FloatingActionButton
shadow_length:用来指定高度(阴影大小)
cornerRadius:用来指定拐角处的平滑半径大小
导入源码(请直接copy)
源码采用Kotlin,有需要可以直接转为Java,转换方法自行百度
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.view.View
import android.view.ViewGroup
import androidx.annotation.*
import com.example.rubbishcommunity.R
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)
fabId = ta.getResourceId(R.styleable.GapBottomNavigationView_anchor_fab, 0)
shadowLength = ta.getFloat(R.styleable.GapBottomNavigationView_shadow_length, 6.toFloat())
cornerRadius = ta.getFloat(R.styleable.GapBottomNavigationView_corner_radius, 12.toFloat())
ta.recycle()
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
//测量时才能拿到凹陷的View
val fab = (parent as ViewGroup).findViewById<View>(fabId)
centerRadius = fab.width / 2.toFloat() + cornerRadius
invalidate()
}
@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()
//关闭硬件加速才能有阴影效果
setLayerType(LAYER_TYPE_SOFTWARE, paint)
//按背景色填充背景
paint.apply {
style = Paint.Style.FILL
color = backgroundTintList?.defaultColor ?: Color.BLACK
maskFilter = null
isAntiAlias = true
//添加阴影
setShadowLayer(shadowLength, 0.toFloat(), 0.toFloat(), Color.LTGRAY)
}
canvas.drawPath(path, paint)
}
}
建议:结合我的代码并利用 paint(画笔) 随意更改为你想要的形状
在 MainActivity 中使用
Menu :
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/navigation_home"
android:icon="@drawable/nav_selector_home"
android:title="首页"
app:showAsAction="always" />
<item
android:id="@+id/navigation_find"
android:icon="@drawable/nav_selector_find"
android:title="发现"
app:showAsAction="always" />
<item
android:id="@+id/navigation_null"
android:enabled="false"
android:checked="false"
android:checkable="false"
android:icon="@null"
android:title="@null" />
<item
android:id="@+id/navigation_message"
android:icon="@drawable/nav_selector_message"
android:title="消息"
app:showAsAction="always" />
<item
android:id="@+id/navigation_mine"
android:icon="@drawable/nav_selector_mine"
android:title="我的"
app:showAsAction="always" />
</menu>
XML :
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btn_send_mqtt_smg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:clickable="true"
android:tint="@color/white"
app:layout_constraintBottom_toBottomOf="@+id/maincontainer"
app:layout_constraintEnd_toEndOf="@+id/maincontainer"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/icon_email" />
<FrameLayout
android:id="@+id/maincontainer"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0">
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<com.example.rubbishcommunity.ui.widget.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:padding="8dp"
android:backgroundTint="@color/white"
app:labelVisibilityMode="labeled"
app:cornerRadius="12dp"
app:anchor_fab="@id/fab_add"
app:shadow_length="12"
app:elevation="5dp"
app:itemBackground="@null"
app:itemIconTint="@color/black"
app:itemTextColor="@color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="@menu/navigation"
tools:targetApi="lollipop" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="36dp"
android:backgroundTint="@color/colorWhite"
android:elevation="2dp"
android:src="@android:drawable/ic_input_add"
android:tint="@color/black"
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="@color/colorAccent" />
</androidx.constraintlayout.widget.ConstraintLayout>
我的效果就是这样咯
093143d5ebb666338bc164a6bd339da5.jpg
喜欢不要忘了点赞关注~~