在Android UI中旋转和显示图像的最有效方法是什么?

时间:2015-10-18 23:43:31

标签: java android performance drawing image-rotation

我想经常旋转 图片(每秒多次)并显示。为此做准备,必须缩放图像以适合视图。

我首先做的是定义一个Drawable,将其加载到ImageView并调用setRotation()。但它自API级别11以来只是支持,而不是9.

<ImageView
    android:id="@+id/image"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:adjustViewBounds="true"
    android:scaleType="fitCenter"
    android:src="@drawable/image" />

这会产生非常糟糕的性能(如预期的那样),但最有效/最合适的方法是什么?如果这很重要,图像包含透明区域。我应该使用硬件加速吗?

This回答与此主题有某种关联。但在我的情况下,旋转必须多次完成,而缩放只需要进行一次。

在我工作了很长一段时间后,我陷入困境,并在这里寻求帮助。如果您有其他问题,请发表评论,我很乐意回答。

1 个答案:

答案 0 :(得分:1)

我假设您的传感器读数是 push 模型,您可以在其中设置侦听器以更改传感器,而不是 pull (轮询)模型。我还假设回调发生在一个非UI线程上(如果不是,它应该)。

由于您正在旋转图像,我还会假设您的源位图是圆形图像,如表盘上的针等。

  • 创建一个View子类。我称之为SensorView。你自己会做绘图,所以你真的不需要ImageView
  • 您的传感器回调需要对活动的引用,或者有一些方法在UI线程上运行更新。
  • 当您的传感器触发时,获取读数并将其设置在视图上。

    actviity.runOnUiThread(new Runnable() {
        @Override
        public void run() {
            mSensorView.setReading(val);
        }
    });
    
  • SensorView将有一个读数值,一个Bitmap用于图像,一个Matrix用于转换位图。

    public class SensorView extends View {
    
        private float mReading;  // I use float as an example; use whatever your sensor device supports
        private Bitmap mBitmap;
        private Matrix mMatrix;
        private RectF mBitmapRect;
        private RectF mViewRect;
    
        public SensorView(Context context) {
            this(context, null);
        }
    
        public SensorView(Context context, AttributeSet attrs) {
            super(context, attrs);
    
            // set up your Bitmap here; don't worry about scaling it yet
            mBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.sensor_bitmap);
    
            mMatrix = new Matrix();
            mBitmapRect = new RectF(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
            mViewRect = new RectF();
        }
    
        public void setReading(float reading) {
            mReading = reading;
            postInvalidate();   // refresh the display
        }
    
        @Override
        public void onDraw(Canvas canvas) {
    
            mViewRect.right = getWidth();
            mViewRect.bottom = getHeight();
            mMatrix.reset();
    
            // center and scale the image
            mMatrix.setRectToRect(mBitmapRect, mViewRect, ScaleToFit.CENTER);
    
            // do the rotation
            float theta = ... // compute angle based on mReading
            mMatrix.preRotate(theta, mBitmapRect.centerX(), mBitmapRect.centerY());
    
            // draw the bitmap with the matrix
            canvas.drawBitmap(mBitmap, mMatrix, null);
        }
    }
    

[经过一些测试后编辑]