8

我正在为 android 应用程序开发自定义视图,类似于Mind the Robot提供的 Analog Gauge 示例代码。

从列出的站点运行代码,我在屏幕上看到了这个:

(摩托罗拉机器人,2.2.3),(模拟器,4.0.3)

有一个箭头

(Xoom, 4.0.3)(其他手机, 4.0.3)

没有箭头

手不见了!

正在进行绘图调用(我可以在 logcat 中看到它们),但是调用绘制的画布元素是不可见的。

不过,它不依赖于 API 级别;如果我以正确的方式将它导入到项目中,当我在 Xoom 上运行它时,它就会显示出来。

但是,当我将文件移动到不同的项目文件夹(相同的源代码,相同的布局)时,它又会丢失表盘。

这是怎么回事?相同的代码如何在不同的设备上产生如此不同的结果?

4

6 回答 6

13

所以,我的谜团中的关键线索似乎是它在模拟器上工作,而不是在硬件设备上。

硬件渲染

我确实仔细阅读了 Android 开发者网站上的硬件渲染页面,但显然不够仔细。

http://developer.android.com/guide/topics/graphics/hardware-accel.html

虽然它确实提到 API 从版本 11 开始可用,但它并没有说默认情况下所有应用程序都启用硬件渲染,从 API 级别 14 (ICS) 开始

这对我们意味着什么?

几乎一切都更快;除了一些不起作用的东西。

我设法违反了其中两个,但没有意识到:

  • Canvas.DrawTextOnPath()
  • Paint.setShadowLayer()

API 参考中没有提到它(或者我能找到的任何其他地方,当然也没有被 Lint 检查),但是使用任何列出的操作都可以做一些奇怪的事情。

就我而言, Canvas.DrawTextOnPath() 似乎工作得很好。

但是当Android注意到我在手上使用的油漆设置了阴影层时,它会默默地忽略它。

我如何知道我的 View 是否是硬件加速的?

从上面的文档链接:

有两种不同的方法可以检查应用程序是否是硬件加速的:

  • 如果视图附加到硬件加速窗口,View.isHardwareAccelerated()返回 true。
  • 如果 Canvas 是硬件加速的,Canvas.isHardwareAccelerated()返回 true

如果您必须在绘图代码中执行此检查,请尽可能使用 Canvas.isHardwareAccelerated() 而不是 View.isHardwareAccelerated()。当视图附加到硬件 > 加速窗口时,仍然可以使用非硬件加速的 Canvas 进行绘制。例如,当出于缓存目的将视图绘制到位图中时,就会发生这种情况。

在我的情况下,似乎发生了相反的情况。自定义视图记录它不是硬件加速的;但是,画布报告它是硬件加速的。

解决方法和固定装置

最简单的解决方法是强制自定义视图进行软件渲染。根据文档,这可以通过以下方式完成:

myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

或者,您可以删除有问题的操作,并保持打开硬件渲染。

从我的不幸中吸取教训。祝你好运。

于 2012-07-12T21:27:59.727 回答
3

我将它放入 init() 并在那之后工作正常。

    private void init() {
    setLayerType(myView.LAYER_TYPE_SOFTWARE, null);
    ....
}
于 2013-12-08T20:51:39.653 回答
2

使用 myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); 建议我可以看到手。但我还有一个问题:我看到比例尺只写了 0!如图所示和架构外的两个策略零:(GALAXY NEXUS 4.2.1)

在此处输入图像描述

我的 drawScale() 方法如示例中所示:

 private void drawScale(Canvas canvas) {
        canvas.drawOval(scaleRect, scalePaint);

        canvas.save(Canvas.MATRIX_SAVE_FLAG);
        for (int i = 0; i < totalNicks; ++i) {
            float y1 = scaleRect.top;
            float y2 = y1 - 0.020f;

            canvas.drawLine(0.5f, y1, 0.5f, y2, scalePaint);


            if ((i % 5) == 0) {
                int value = nickToDegree(i);

                if ((value >= minDegrees) && (value <= maxDegrees)) {
                    String valueString = Integer.toString(value);
                    canvas.drawText(valueString, 0.5f, y2 - 0.015f, scalePaint);

                }
            }

            canvas.rotate(degreesPerNick, 0.5f, 0.5f);


        }
        canvas.restore();

    }
于 2014-10-19T14:04:18.527 回答
0

就我而言,我做了这个:

 AnalogView bar = (AnalogView) findViewById(R.id.AnalogBar);
    bar.setLayerType(bar.LAYER_TYPE_SOFTWARE, null);
if (value_list.size()>0)   bar.SetData(Double.parseDouble(value_list.get(value_list.size()-1)));

AnalogView 中的 SetData 在哪里

public  void SetData(double data) {
    setHandTarget((float)data);
  invalidate();
}
于 2014-05-01T14:33:19.150 回答
0

在 Galaxy S4 安卓 4.4.2 上

TYPE_TEMPERATURE已弃用

利用

TYPE_AMBIENT_TEMPERATURE

于 2014-06-07T17:25:07.797 回答
-1

对于在初始化时按比例绘制文本有问题的任何人,请执行以下操作:

scalePaint.setLinearText(true);

于 2014-12-27T18:12:37.817 回答