7

我正在编写一个显示信号的自定义视图。为了缩短我的 onDraw() 时间,我将迄今为止绘制的所有内容缓存在位图中,并在每个 onDraw() 调用中附加到该位图中。通过这样做,我可以节省大量时间,因为我一次只需要绘制几个固定点,而不是重做整个事情。

不过,有一件事情困扰着我——它显示为直接在提供的画布上绘图提供了比先在位图上绘图然后在画布上绘制位图更“准确”的绘图。通过查看下图的下部,您可以看到不同之处:

查看信号的下部以查看差异 - 有相同的 drawLine 调用

我在https://github.com/gardarh/android-uglybitmapdrawing/上传了一个显示差异的演示项目,但相关代码如下:

@Override
public void onDraw(Canvas canvas) {
    if(cachedBitmap == null) {
        cachedBitmap = Bitmap.createBitmap(getWidth(), 200, Config.ARGB_8888);
        cachedCanvas = new Canvas(cachedBitmap);
    }

    for(int i = 0; i < COORDS.length; i++) {
        float[] curCoords = COORDS[i];
        canvas.drawLine(curCoords[0], curCoords[1], curCoords[2], curCoords[3], linePaint);
        cachedCanvas.drawLine(curCoords[0], curCoords[1], curCoords[2], curCoords[3], linePaint);
    }
    canvas.drawBitmap(cachedBitmap, 0, 120, null);
}

为什么两条痕迹不一样,更重要的是,我怎样才能让下面的痕迹看起来像上面的一样?

4

3 回答 3

3

产生差异的原因是画布绘制是由硬件加速(GPU)完成的,而位图绘制是由软件(CPU)完成的。如果禁用硬件加速,它们将变得完全相同。如果将 X 坐标乘以 10,您会发现不同之处在于线条的连接方式。这些只是微小的一个像素差异,我不会打扰它们。我不确定哪个更准确,它们看起来只是略有不同的实现。

于 2013-06-10T14:25:53.737 回答
3

Android 框架 API 为不需要大动态更改的简单动画提供 2D 绘图 API。使用这些 API 有两种实现方式。

1. 绘制到视图
2. 在画布上绘制

1.画一个圆来查看

当你的UI不需要在应用程序中动态改变时,画一个来查看是一个更好的选择。这可以通过扩展 View 类并定义一个onDraw()回调方法来实现。
使用提供给您的 Canvas 进行所有绘图,
使用各种 Canvas.draw...() 方法(例如:canvas.drawCircle(x / 2, y / 2, radius, paint);)。onDraw() 是最初绘制视图时调用的回调方法。

下面是一个简单的画圆示例代码:-

MainActivity.java

 public class MainActivity extends Activity {

     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(new MyView(this));
     }

     public class MyView extends View {
         public MyView(Context context) {
              super(context);
              // TODO Auto-generated constructor stub
         }

         @Override
         protected void onDraw(Canvas canvas) {
            // TODO Auto-generated method stub
            super.onDraw(canvas);
            int x = getWidth();
            int y = getHeight();
            int radius;
            radius = 100;
            Paint paint = new Paint();
            paint.setStyle(Paint.Style.FILL);
            paint.setColor(Color.WHITE);
            canvas.drawPaint(paint);
            // Use Color.parseColor to define HTML colors
            paint.setColor(Color.parseColor("#FB9J2F"));
            canvas.drawCircle(x / 2, y / 2, radius, paint);
        }
     } }

2. 在画布上绘制矩形

要在应用程序中需要定期重新绘制自身的地方绘制动态 2D 图形,在画布上绘制是更好的选择。画布作为一个界面为您工作,您将在其上绘制图形的实际表面。

如果您需要创建一个新的 Canvas,那么您必须定义实际执行绘图的位图。画布始终需要位图。

下面的例子解释了绘制一个矩形:

-activity_main.xml

<?xml version="1.0" encoding="utf-8"?>  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/mylayout">     </LinearLayout>

MainActivity.java

public class MainActivity extends Activity {
     @Override
     public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Paint paint = new Paint();
        paint.setColor(Color.parseColor("#DD4N5C"));
        Bitmap bitmap = Bitmap.createBitmap(512, 800, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap); 
        canvas.drawRect(150, 150, 250, 250, paint); 
        LinearLayout layout = (LinearLayout) findViewById(R.id.mylayout);
        layout.setBackgroundDrawable(new BitmapDrawable(bitmap));   
     }

     }
于 2016-02-27T21:08:03.087 回答
0

我不同意您通过位图路线节省了很多。您可能会考虑存储绘制信号并将其转换为可以序列化/反序列化的 JSON 对象的数据结构。至于您的问题,这是一个有根据的猜测,但它更多地与绘制信号的重新缩放有关,因为您在创建位图时没有使用 getHeight() 。

于 2013-06-10T14:07:58.857 回答