ImageView 显示图片

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

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

<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<Runnable>()); 
        // 添加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); 
}

效果图


发布评论
IT虾米网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

ThreadLocal的使用与源码解析详解
你是第一个吃螃蟹的人
发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。