PaintCode绘图代码android使用像素而不是点/ DP

Hix*_*eld 2 paintcode

注意:是的我知道在Android中还有其他方法可以做按钮,但这只是一个展示我的问题的例子(实际按钮远比复杂得多).所以请不要回复为Android中的按钮提供其他解决方案,我正在寻找使用PaintCode的解决方案...

我在iOS中使用PaintCode多年来绘制自定义按钮,它的工作非常出色.我想为Android做同样的事情,并有以下问题:

  1. 在PaintCode中,我绘制了一个按钮,该按钮基本上是一个半径为20磅的圆角矩形.
  2. 我绘制一个框架然后使用弹簧设置正确的调整大小行为(见屏幕截图).
  3. 结果是,无论按钮的大小是多少(=框架),角落总是会有20个点的圆角.基本上是一个可调整大小的按钮.

这在iOS上非常有效,但在Android上,半径是20 像素而不是点,导致半径小到很小(现在使用高分辨率设备).

或者通常我在PaintCode中使用PaintCode生成的draw方法绘制的所有绘图都很小.

它表示生成的绘图代码没有考虑设备的规模(就像在iOS上一样).

在此输入图像描述

看看https://www.paintcodeapp.com/documentation/android节"缩放"PaintCode建议在android中使用密度指标来执行缩放.这确实有效,但是生成的图形模糊,我猜这是因为我们因缩放而绘制的分辨率较低.所以它不是一个可行的解决方案

class Button1 @JvmOverloads constructor(
        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : Button(context, attrs, defStyleAttr) {

    var frame = RectF()

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        val displayDensity = resources.displayMetrics.density
        canvas?.scale(displayDensity, displayDensity)
        frame.set(0f,0f,width.toFloat()/displayDensity,height.toFloat()/displayDensity)
        StyleKitName.drawButton1(canvas, frame)
    }
}
Run Code Online (Sandbox Code Playgroud)

有什么建议可以解决吗?这是PaintCode中的错误吗?

小智 8

我是开发人员.抱歉,答案很长.

TLDR:自己处理扩展,例如你的方式.将View的layerType切换为软件以避免模糊的结果模糊.

首先,我完全理解混乱,对于iOS它只是工作,在Android中你必须摆弄一些尺度.如果它只是我喜欢的那样,以及其他PaintCode用户也会更有意义.然而,这不是一个错误.问题是UIKit和android.graphic之间的区别.

在UIKit中,距离以点为单位进行测量.这意味着如果你绘制一个直径为40磅的圆圈,它在各种iOS设备上的尺寸应该更小.PaintCode采用了这个约定,你在PaintCode的用户界面中看到的所有数字,如形状的位置,笔划宽度或半径 - 一切都在点.PaintCode生成的绘图代码不仅与分辨率无关(即,您可以调整大小/缩放它并保持清晰度),还可以独立显示密度(在视网膜显示器,常规显示器和视网膜高清显示器上呈现相同大小).并且代码没有任何特殊之处.它看起来像这样:

NSBezierPath* rectanglePath = [NSBezierPath bezierPathWithRect: NSMakeRect(0, 0, 100, 50)];
[NSColor.grayColor setFill];
[rectanglePath fill];
Run Code Online (Sandbox Code Playgroud)

因此显示缩放由UIKit处理.隐含的比例也取决于上下文.如果你在某个UIView子类的drawRect:中调用绘图代码,它会占用显示密度,但是如果你在自定义UIImage中绘图,它会获取该图像的密度.魔法.

然后我们添加了对Android的支持.android.graphic中的所有度量都以像素表示.Android没有做任何UIKit的"显示密度"魔术.另外,没有一种好方法可以找出绘图代码范围内的密度.您需要访问资源.所以我们可以将它作为参数添加到所有绘图方法中.但是,如果您不打算将图形发布到显示器但是您要创建图像(您要发送给您的朋友或其他什么),该怎么办?那么你不需要显示密度,而是图像密度.好吧,如果添加一个参数,我们不应该添加资源,而是将密度本身作为浮点数并在每个绘图方法中生成缩放.现在如果你真的不关心密度怎么办?如果您关心的是您的绘图填充某个矩形并且可能具有最佳分辨率,该怎么办?实际上我认为通常就是这种情况.拥有如此多的不同显示分辨率和显示密度使得"一种物理尺寸的元素适合所有"的方法在我看来非常小.因此在大多数情况下,密度参数将是无关紧要的.我们决定留下如何处理用户规模的决定.

现在为缩放绘图模糊性.这是UIKit和android.graphics之间的另一个区别.所有开发人员都应该了解CoreGraphics在渲染具有多个对象的大型场景时速度不是很快.如果您正在编写性能敏感的应用程序,您应该考虑使用SpriteKit或Metal.这样做的好处是,您不必限制在CoreGraphics中可以执行的操作,并且您几乎总能获得非常准确的结果.缩放就是这样一个例子.你可以应用巨大的规模,结果仍然很清晰.如果您想要更多的硬件加速,请使用不同的API并自行处理限制(例如您可以在GPU中放置大的纹理).

Android走了其他路.他们的android.graphic api可以在两种模式下工作 - 没有硬件加速(他们称之为软件)或硬件加速(他们称之为硬件).它仍然是相同的API,但其中一种硬件模式有一些重要的限制.这包括比例,模糊(因此阴影),一些混合模式等. https://developer.android.com/guide/topics/graphics/hardware-accel.html#unsupported

他们决定,每一个视图将使用硬件模式在默认情况下,如果目标API等级> = 14,你当然也可以将其关闭,并奇迹般地您的缩放按钮,将是很好的和尖锐.

我们提到您需要在我们的文档页面"层的类型"部分中关闭硬件加速https://www.paintcodeapp.com/documentation/android 它也在Android文档中https://developer.android.com/guide /topics/graphics/hardware-accel.html#controlling