首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PaintCode绘图代码android使用的是像素而不是点/DP

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

Stack Overflow用户
提问于 2017-09-27 14:59:35
回答 2查看 760关注 0票数 3

注意:是的,我知道在Android中还有其他的按钮处理方法,但这只是一个例子来说明我的问题( actuall按钮要复杂得多)。因此,请不要回答在提供其他解决方案按钮在安卓,我正在寻找一个解决方案与PaintCode.

多年来,我一直使用PaintCode来绘制自定义按钮,它的工作原理非常出色。我也想对android做同样的事情,并有以下问题:

  1. 在PaintCode中,我画一个按钮,它基本上是一个圆角矩形,半径为20点。
  2. 我画一个框架周围,然后设置正确的大小行为使用弹簧(见截图)。
  3. 其结果是,无论按钮的大小将是(=框架),角将永远是完美的圆角与20分。基本上是个可调整大小的按钮。

这在iOS上运行得很好,但是在安卓系统上,radius是20个像素而不是点,从而产生了一个远到小的半径(现在是高分辨率设备)。

或者在一般情况下,使用PaintCode生成的绘图方法绘制PaintCode时,我在PaintCode中绘制的所有绘图都是小的。

它会使生成的绘图代码没有考虑到设备的规模(就像在iOS上那样)。

查看https://www.paintcodeapp.com/documentation/android部分,“缩放”PaintCode建议在安卓系统中使用密度度量来执行缩放。这确实有效,但使生成的绘图模糊,我想这是因为我们绘制的分辨率较低,因为缩放。所以这不是一个可行的解决方案。

代码语言:javascript
复制
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)
    }
}

有解决这个问题的建议吗?这是PaintCode中的一个bug吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-09-27 20:25:32

我是开发商。很抱歉给你这么长的答案。

TLDR:自己处理缩放,例如你的方式。切换视图的layerType到软件,以避免模糊的结果规模。

首先,我完全理解这种混淆,对于iOS来说,它只是起作用,而在安卓系统中,你必须摆弄一些尺度。如果它能正常工作,那就更有意义了--我很喜欢它,其他的PaintCode用户也会这么做。但这不是窃听器。问题在于UIKit和android.graphic之间的区别。

在UIKit中,以点为单位来测量距离。这意味着,如果你画一个直径40点的圆圈,那么在不同的iOS设备上,它的尺寸应该会更小一些。PaintCode采用了这个惯例和你在PaintCode的用户界面中看到的所有数字,比如形状、笔划宽度或半径的位置--所有的东西都是在点上的。PaintCode生成的绘图代码不仅与分辨率无关(即可以调整大小/缩放,保持清晰度),而且与显示密度无关(在视网膜显示、常规显示和视网膜高清显示上呈现大致相同的大小)。代码没有什么特别之处。看起来是这样的:

代码语言:javascript
复制
NSBezierPath* rectanglePath = [NSBezierPath bezierPathWithRect: NSMakeRect(0, 0, 100, 50)];
[NSColor.grayColor setFill];
[rectanglePath fill];

因此显示缩放是由UIKit处理的。此外,隐式尺度也取决于上下文。如果在drawRect: UIView子类中调用绘图代码,则会获得显示密度,但如果要在自定义UIImage中绘图,则会获取该图像的密度。魔术。

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

现在是的模糊性的缩放绘图。这是UIKit和android.graphics的另一个不同之处。所有开发人员都应该明白,当涉及到用多个对象呈现大场景时,CoreGraphics不是很快。如果您是编程性能敏感的应用程序,您可能应该考虑使用SpriteKit或金属。这样做的好处是,您在CoreGraphics中所能做的事情并没有受到限制,而且您几乎总是能够得到非常准确的结果。缩放就是一个这样的例子。你可以使用巨大的规模,结果仍然是脆的。如果您想要更多的HW加速,使用不同的API并自己处理这些限制(比如您可以在GPU中安装多大的纹理)。

安卓走了另一条路。他们的android.graphic api可以在两种模式下工作--没有HW加速(他们称之为软件)或HW加速(他们称之为硬件)。它仍然是相同的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中。

票数 9
EN

Stack Overflow用户

发布于 2017-09-27 15:40:07

我记得有一个类似的问题,在与PaintCode支持人员交谈之后,我们想出了一个将DP转换为PX的函数。因此,比如说,在Android系统中,考虑到不同的显示密度,这20个点将被转换成“任何”像素。

长话短说,这是PaintCode支持答案的总结:

安卓在其绘图API中不支持独立于设备的像素,这是iOS和安卓行为不同的原因。使用UIKit时,输入的坐标以点为单位,因此它负责显示密度本身。在Android中生成位图时,需要考虑显示密度。

这是我创建的函数:

代码语言:javascript
复制
private static PointF convertDPtoPX(float widthDP, float heightDP) {
    Context context = getAppContext();
    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    float widthPX = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, widthDP, metrics);
    float heightPX = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, heightDP, metrics);

    return new PointF(widthPX, heightPX);
}

下面是一个如何调用它的示例:

代码语言:javascript
复制
Bitmap myButton = StyleKit.imageOfMyButton(convertDPtoPX(widthDP, heightDP));

当然,在本例中,由于项目的具体情况,我使用的是myButton (StyleKit.imageOfMyButton)位图。您需要调整示例以满足您的需要。

例如,您可以将该radius作为PaintCode中的外部参数,使每个平台负责提供其价值。比如:

代码语言:javascript
复制
// In Android, convert 20DP to 20PX based on the above function.
// In iOS, just pass 20. 
StyleKitName.drawButton1(canvas, frame, radius)

我希望这能帮到你。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46451186

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档