Skip to content

Instantly share code, notes, and snippets.

@AbGhost-cyber
Created October 10, 2020 16:53
Show Gist options
  • Save AbGhost-cyber/e2d21ad91a92a58e11e1bd9054d067e7 to your computer and use it in GitHub Desktop.
Save AbGhost-cyber/e2d21ad91a92a58e11e1bd9054d067e7 to your computer and use it in GitHub Desktop.
class CurvedBottomNavigationView : BottomNavigationView {
private var mPath: Path? = null
private var mPaint: Paint? = null
/** the CURVE_CIRCLE_RADIUS represent the radius of the fab button */
private val CURVE_CIRCLE_RADIUS = 256 / 2
// the coordinates of the first curve
private val mFirstCurveStartPoint: Point = Point()
private val mFirstCurveEndPoint: Point = Point()
private val mFirstCurveControlPoint1: Point = Point()
private val mFirstCurveControlPoint2: Point = Point()
//the coordinates of the second curve
private var mSecondCurveStartPoint: Point = Point()
private val mSecondCurveEndPoint: Point = Point()
private val mSecondCurveControlPoint1: Point = Point()
private val mSecondCurveControlPoint2: Point = Point()
private var mNavigationBarWidth = 0
private var mNavigationBarHeight = 0
constructor(context: Context?) : super(context!!) {
init()
}
constructor(context: Context?, attrs: AttributeSet?) : super(
context!!,
attrs
) {
init()
}
constructor(
context: Context?,
attrs: AttributeSet?,
defStyleAttr: Int
) : super(context!!, attrs, defStyleAttr) {
init()
}
private fun init() {
mPath = Path()
mPaint = Paint()
mPaint!!.style = Paint.Style.FILL_AND_STROKE
mPaint!!.color = Color.WHITE
setBackgroundColor(Color.TRANSPARENT)
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
// get width and height of navigation bar
// Navigation bar bounds (width & height)
mNavigationBarWidth = width
mNavigationBarHeight = height
// the coordinates (x,y) of the start point before curve
mFirstCurveStartPoint.set(
mNavigationBarWidth / 2 - CURVE_CIRCLE_RADIUS * 2 - CURVE_CIRCLE_RADIUS / 3,
0
)
// the coordinates (x,y) of the end point after curve
mFirstCurveEndPoint.set(
mNavigationBarWidth / 2,
CURVE_CIRCLE_RADIUS + CURVE_CIRCLE_RADIUS / 4
)
// same thing for the second curve
mSecondCurveStartPoint = mFirstCurveEndPoint
mSecondCurveEndPoint.set(
mNavigationBarWidth / 2 + CURVE_CIRCLE_RADIUS * 2 + CURVE_CIRCLE_RADIUS / 3,
0
)
// the coordinates (x,y) of the 1st control point on a cubic curve
mFirstCurveControlPoint1.set(
mFirstCurveStartPoint.x + CURVE_CIRCLE_RADIUS + CURVE_CIRCLE_RADIUS / 4,
mFirstCurveStartPoint.y
)
// the coordinates (x,y) of the 2nd control point on a cubic curve
mFirstCurveControlPoint2.set(
mFirstCurveEndPoint.x - CURVE_CIRCLE_RADIUS * 2 + CURVE_CIRCLE_RADIUS,
mFirstCurveEndPoint.y
)
mSecondCurveControlPoint1.set(
mSecondCurveStartPoint.x + CURVE_CIRCLE_RADIUS * 2 - CURVE_CIRCLE_RADIUS,
mSecondCurveStartPoint.y
)
mSecondCurveControlPoint2.set(
mSecondCurveEndPoint.x - (CURVE_CIRCLE_RADIUS + CURVE_CIRCLE_RADIUS / 4),
mSecondCurveEndPoint.y
)
mPath!!.reset()
mPath!!.moveTo(0f, 0f)
mPath!!.lineTo(mFirstCurveStartPoint.x.toFloat(), mFirstCurveStartPoint.y.toFloat())
mPath!!.cubicTo(
mFirstCurveControlPoint1.x.toFloat(), mFirstCurveControlPoint1.y.toFloat(),
mFirstCurveControlPoint2.x.toFloat(), mFirstCurveControlPoint2.y.toFloat(),
mFirstCurveEndPoint.x.toFloat(), mFirstCurveEndPoint.y.toFloat()
)
mPath!!.cubicTo(
mSecondCurveControlPoint1.x.toFloat(), mSecondCurveControlPoint1.y.toFloat(),
mSecondCurveControlPoint2.x.toFloat(), mSecondCurveControlPoint2.y.toFloat(),
mSecondCurveEndPoint.x.toFloat(), mSecondCurveEndPoint.y.toFloat()
)
mPath!!.lineTo(mNavigationBarWidth.toFloat(), 0f)
mPath!!.lineTo(mNavigationBarWidth.toFloat(), mNavigationBarHeight.toFloat())
mPath!!.lineTo(0f, mNavigationBarHeight.toFloat())
mPath!!.close()
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.drawPath(mPath!!, mPaint!!)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment