Android 带有边框自定义视图或矢量可绘制对象的按钮叠加层
Android button overlay with border custom view or vector drawable
我想创建一个带有圆框的自定义浮动操作按钮。喜欢下图
我最终为它制作了自定义视图。但这太麻烦了。
这里是onDraw
函数
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val cx = (width / 2).toFloat()
val cy = (height / 2).toFloat()
val hShift = outerRadius * .4
val vShift = outerRadius * .05
circle.set(
(cx - outerRadius - hShift).toFloat(), (cy - 3 * outerRadius + vShift).toFloat(),
(cx + outerRadius- hShift).toFloat(), (cy - outerRadius+vShift).toFloat()
)
path.arcTo(circle, 0F, 85F)
path.lineTo(cx,cy-outerRadius)
circle.set(cx - outerRadius, cy - outerRadius, cx + outerRadius, cy + outerRadius)
path.arcTo(circle, 90F, 180F)
path.lineTo(cx,cy-outerRadius)
path.lineTo(cx, cy+outerRadius)
circle.set(
(cx - outerRadius- hShift).toFloat(), (cy + outerRadius - vShift).toFloat(),
(cx + outerRadius- hShift).toFloat(), (cy + 3 * outerRadius - vShift).toFloat()
)
path.arcTo(circle, 275F, 90F)
canvas.drawPath(path, paint)
}
我的问题:这样做正确吗?
我在想一个可绘制的矢量作为背景
PS:我也试过 BottomNavigationView
但它是设计在底部的
是的,使用矢量可绘制对象作为背景会是一个更好的策略。 Android 支持 svg。只需将 svg 导入您的 res/drawable 文件夹并将其用作按钮的背景。该按钮将自动符合您的需要。
希望这有帮助
避免在 onDraw() 方法中进行计算,因为每次都会调用它,这对应用程序的性能不利
可绘制背景是最简单的方法,但我发现过去我无法使它像我希望的那样一致地工作。您可能需要同一张图片的多种变体来覆盖多种屏幕尺寸。
一种选择是使用 XML 形状设计您的自定义晶圆厂。虽然这不是我的专业领域,但我有一些资源可以提供帮助。
Indepth Intro To XML Shape Building
Whosebug - Stacking multiple shapes on top of each other in XML
Building A Custom Floating Action Button - XML (2017)
Whosebug - Example of more complex XML Shape using Vector Drawable
还有一个选项在性能方面比您当前的实施要好得多。如果您可以在 link..
中重新实施解决方案,这可能效果最好
link 是关于使用三次贝塞尔曲线在底栏上构建形状,看来您可以在任何视图类型上使用它,而不仅仅是如图所示的底栏。我将 post 这个 link 用来了解不同之处的相关代码。
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//point calculation
mPath.reset();
mPath.moveTo(0, 0);
mPath.lineTo(mFirstCurveStartPoint.x, mFirstCurveStartPoint.y);
mPath.cubicTo(mFirstCurveControlPoint1.x, mFirstCurveControlPoint1.y,
mFirstCurveControlPoint2.x, mFirstCurveControlPoint2.y,
mFirstCurveEndPoint.x, mFirstCurveEndPoint.y);
mPath.cubicTo(mSecondCurveControlPoint1.x, mSecondCurveControlPoint1.y,
mSecondCurveControlPoint2.x, mSecondCurveControlPoint2.y,
mSecondCurveEndPoint.x, mSecondCurveEndPoint.y);
mPath.lineTo(mNavigationBarWidth, 0);
mPath.lineTo(mNavigationBarWidth, mNavigationBarHeight);
mPath.lineTo(0, mNavigationBarHeight);
mPath.close();
}
您的 OnDraw 最终看起来像什么 -
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(mPath, mPaint);
}
我想创建一个带有圆框的自定义浮动操作按钮。喜欢下图
我最终为它制作了自定义视图。但这太麻烦了。
这里是onDraw
函数
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val cx = (width / 2).toFloat()
val cy = (height / 2).toFloat()
val hShift = outerRadius * .4
val vShift = outerRadius * .05
circle.set(
(cx - outerRadius - hShift).toFloat(), (cy - 3 * outerRadius + vShift).toFloat(),
(cx + outerRadius- hShift).toFloat(), (cy - outerRadius+vShift).toFloat()
)
path.arcTo(circle, 0F, 85F)
path.lineTo(cx,cy-outerRadius)
circle.set(cx - outerRadius, cy - outerRadius, cx + outerRadius, cy + outerRadius)
path.arcTo(circle, 90F, 180F)
path.lineTo(cx,cy-outerRadius)
path.lineTo(cx, cy+outerRadius)
circle.set(
(cx - outerRadius- hShift).toFloat(), (cy + outerRadius - vShift).toFloat(),
(cx + outerRadius- hShift).toFloat(), (cy + 3 * outerRadius - vShift).toFloat()
)
path.arcTo(circle, 275F, 90F)
canvas.drawPath(path, paint)
}
我的问题:这样做正确吗? 我在想一个可绘制的矢量作为背景
PS:我也试过 BottomNavigationView
但它是设计在底部的
是的,使用矢量可绘制对象作为背景会是一个更好的策略。 Android 支持 svg。只需将 svg 导入您的 res/drawable 文件夹并将其用作按钮的背景。该按钮将自动符合您的需要。 希望这有帮助
避免在 onDraw() 方法中进行计算,因为每次都会调用它,这对应用程序的性能不利
可绘制背景是最简单的方法,但我发现过去我无法使它像我希望的那样一致地工作。您可能需要同一张图片的多种变体来覆盖多种屏幕尺寸。
一种选择是使用 XML 形状设计您的自定义晶圆厂。虽然这不是我的专业领域,但我有一些资源可以提供帮助。
Indepth Intro To XML Shape Building
Whosebug - Stacking multiple shapes on top of each other in XML
Building A Custom Floating Action Button - XML (2017)
Whosebug - Example of more complex XML Shape using Vector Drawable
还有一个选项在性能方面比您当前的实施要好得多。如果您可以在 link..
中重新实施解决方案,这可能效果最好link 是关于使用三次贝塞尔曲线在底栏上构建形状,看来您可以在任何视图类型上使用它,而不仅仅是如图所示的底栏。我将 post 这个 link 用来了解不同之处的相关代码。
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//point calculation
mPath.reset();
mPath.moveTo(0, 0);
mPath.lineTo(mFirstCurveStartPoint.x, mFirstCurveStartPoint.y);
mPath.cubicTo(mFirstCurveControlPoint1.x, mFirstCurveControlPoint1.y,
mFirstCurveControlPoint2.x, mFirstCurveControlPoint2.y,
mFirstCurveEndPoint.x, mFirstCurveEndPoint.y);
mPath.cubicTo(mSecondCurveControlPoint1.x, mSecondCurveControlPoint1.y,
mSecondCurveControlPoint2.x, mSecondCurveControlPoint2.y,
mSecondCurveEndPoint.x, mSecondCurveEndPoint.y);
mPath.lineTo(mNavigationBarWidth, 0);
mPath.lineTo(mNavigationBarWidth, mNavigationBarHeight);
mPath.lineTo(0, mNavigationBarHeight);
mPath.close();
}
您的 OnDraw 最终看起来像什么 -
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(mPath, mPaint);
}