在 Android UI 中旋转和显示图像的最有效方法是什么?
What is the most efficient way to rotate and display an image in an Android UI?
我想经常旋转 图像(每秒多次)和显示它。为此,必须缩放图像以适合视图。
我首先做的是定义一个 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" />
这给出了非常糟糕的性能(正如预期的那样),但是最 effcient/suitable 的方法是什么?图像包含透明区域(如果这很重要)。我应该使用硬件加速吗?
This 答案与此主题有某种关联。但就我而言,旋转必须进行多次,而缩放只需进行一次。
弄了半天卡在这了,求助。如果您还有其他问题,请发表评论,我会很乐意回答。
我假设你的传感器读数是一个 push 模型,你在其中设置一个侦听器以更改传感器,而不是 pull(轮询)模型。我还假设回调发生在一个关闭的 UI 线程上(如果不是,它应该)。
由于您正在旋转图像,我还假设您的源位图是圆形图像,如表盘上的针等。
- 创建一个
View
子类。我称之为 SensorView
。你会自己画画,所以你真的不需要 ImageView
.
- 您的传感器回调将需要对 activity 的引用或有某种方式 运行 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);
}
}
[经过一些测试后编辑]
我想经常旋转 图像(每秒多次)和显示它。为此,必须缩放图像以适合视图。
我首先做的是定义一个 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" />
这给出了非常糟糕的性能(正如预期的那样),但是最 effcient/suitable 的方法是什么?图像包含透明区域(如果这很重要)。我应该使用硬件加速吗?
This 答案与此主题有某种关联。但就我而言,旋转必须进行多次,而缩放只需进行一次。
弄了半天卡在这了,求助。如果您还有其他问题,请发表评论,我会很乐意回答。
我假设你的传感器读数是一个 push 模型,你在其中设置一个侦听器以更改传感器,而不是 pull(轮询)模型。我还假设回调发生在一个关闭的 UI 线程上(如果不是,它应该)。
由于您正在旋转图像,我还假设您的源位图是圆形图像,如表盘上的针等。
- 创建一个
View
子类。我称之为SensorView
。你会自己画画,所以你真的不需要ImageView
. - 您的传感器回调将需要对 activity 的引用或有某种方式 运行 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); } }
[经过一些测试后编辑]