【问题标题】:Android button overlay with border custom view or vector drawable带有边框自定义视图或矢量可绘制的 Android 按钮叠加层
【发布时间】:2019-12-31 09:58:07
【问题描述】:

我想创建一个带有圆形框架的自定义浮动操作按钮。如下图

我最终为它制作了一个自定义视图。但它太有问题了。

这是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 xml android-custom-view vector-graphics android-vectordrawable


    【解决方案1】:

    避免在 onDraw() 方法中进行计算,因为它每次都会被调用,对应用程序的性能不利

    可绘制的背景是最简单的方法,但我过去发现我无法让它像我想要的那样一致。您可能需要同一图像的多个变体来覆盖多种屏幕尺寸。

    一种选择是使用 XML 形状设计您的定制工厂。虽然这不是我的专业领域,但我有一些资源可以提供帮助。

    Indepth Intro To XML Shape Building

    Stackoverflow - Stacking multiple shapes on top of each other in XML

    Building A Custom Floating Action Button - XML (2017)

    Stackoverflow - Example of more complex XML Shape using Vector Drawable

    还有另一种选择,它在性能方面比您当前的实现要好得多。如果您可以重新实现链接中的解决方案,这可能会最有效..

    Advanced Android Shape Canvas

    该链接是关于使用三次 Bézier 曲线在底栏上构建一个形状,看起来您可以在任何视图类型上使用它,而不仅仅是如图所示的底栏。我将发布此链接用于了解不同之处的相关代码。

    @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 很快并没有优化它,我只是想让它工作。我认为贝塞尔曲线是我要去的地方。我尝试了矢量可绘制,但我遇到了缩放问题。
    【解决方案2】:

    是的,使用可绘制矢量作为背景将是一个更好的策略。 Android 支持 svg。只需将 svg 导入 res/drawable 文件夹并将其用作按钮的背景。该按钮将自动符合您的需要。 希望这会有所帮助

    【讨论】:

      猜你喜欢
      • 2010-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多