Android ImageView、TextureView、自定义View显示图片

ImageView 显示图片

在 Android 平台上,显示图片的方式有很多种,其中最为简单的就是 ImageView。

1 . 在 lyaout 布局中,声明好 ImageView

android:id="@+id/image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter"/>

2 . 在 Acitivity 中简单的使用

private ImageView mImageView;
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.acitivity_imageview);
    mImageView = findViewById(R.id.image_view);
    mImageView.setImageResource(R.mipmap.images);
}

SurfaceView 显示图片

SurfaceView 与普通的 view 的区别在于:

  • surfaceview 不需要在 UI 线程绘制,可以在子线程绘制
  • surfaceview 提供了双缓冲的机制,绘制效率高
  • surfaceview 是创建一个置于应用窗口之上的窗口,所以无法不能应用动画、变换和缩放,也没办法叠加

surfaceview 需要实现 SurfaceHolder.Callback 接口,包括三个声明周期

surfaceCreated(SurfaceHolder holder)
surfaceChanged(SurfaceHolder holder, int format, int width, int height) 
surfaceDestroyed(SurfaceHolder holder)

具体的实现代码:

public class ImageSurfaceActivity extends AppCompatActivity implements SurfaceHolder.Callback {
    private SurfaceView mSurfaceView;
    private ExecutorService mThread;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mSurfaceView = new SurfaceView(this);
        setContentView(mSurfaceView);
        initSurfaceView();
    }

    private void initSurfaceView() {
        // 创建一个只有一个线程的线程池,其实用Thread也可以
        mThread = new ThreadPoolExecutor(1, 1, 2000L, TimeUnit.MILLISECONDS, 
                  new LinkedBlockingDeque());
        // 添加SurfaceHolder.callback,在回调中可以绘制
        mSurfaceView.getHolder().addCallback(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        // 执行绘制
        mThread.execute(new DrawRunnable());
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        if (!mThread.isShutdown()) {
            mThread.shutdown();
        }
    }

    private class DrawRunnable implements Runnable {
        @Override
        public void run() {
            Bitmap bimap = BitmapFactory.decodeResource(ImageSurfaceActivity.this.getResources(), 
                           R.mipmap.images);
            SurfaceHolder surfaceHolder = mSurfaceView.getHolder();
            Canvas canvas = surfaceHolder.lockCanvas(); // 获取画布
            Paint paint = new Paint();
            Rect srcRect = new Rect(0, 0, bimap.getHeight(), bimap.getWidth());
            Rect destRect = getBitmapRect(bimap);
            canvas.drawBitmap(bimap, srcRect, destRect, paint);
            surfaceHolder.unlockCanvasAndPost(canvas);
        }
    }

    /**
     * 图片的尺寸和屏幕的尺寸不一样,需要把图片调整居中
     **/
    private Rect getBitmapRect(Bitmap bimap) {
        int bimapHeight = bimap.getHeight();
        int bimapWidth = bimap.getWidth();
        int viewWidth = mSurfaceView.getWidth();
        int viewHeight = mSurfaceView.getHeight();
        float bimapRatio = (float) bimapWidth / (float) bimapHeight; // 宽高比
        float screenRatio = (float) viewWidth / (float) viewHeight;
        int factWidth;
        int factHeight;
        int x1, y1, x2, y2;
        if (bimapRatio > screenRatio) {
            factWidth = viewWidth;
            factHeight = (int)(factWidth / bimapRatio);
            x1 = 0;
            y1 = (viewHeight - factHeight) / 2;
        } else if (bimapRatio < screenRatio) {
            factHeight = viewHeight;
            factWidth = (int)(factHeight * bimapRatio);
            x1 = (viewWidth - factWidth) / 2;
            y1 = 0;
        } else {
            factWidth = bimapWidth;
            factHeight = bimapHeight;
            x1 = 0;
            y1 = 0;
        }
        x2 = x1 + factWidth;
        y2 = y1 + factHeight;
        return new Rect(x1, y1, x2, y2);
    }
}

自定义 View 显示图片

自定义 View 中有三个重要的声明周期:
onLayout() 布局
onMeasure() 测量
onDraw() 绘制
Android 的刷新间隔是 16ms

因为我们只是显示图片,不需要特别复杂的操作,只选取onDraw实现:

private void init() {
    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mBitmap = BitmapFactory.decodeResource(getContext().getResources(), R.mipmap.images);
}
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Rect srcRect = new Rect(0, 0, mBitmap.getHeight(), mBitmap.getWidth());
    Rect destRect = getBitmapRect(mBitmap); // 获取调整后的bitmap的显示位置
    canvas.drawBitmap(mBitmap, srcRect, destRect, mPaint);
}

Android ImageView、TextureView、自定义View显示图片_第1张图片

你可能感兴趣的:(android)