ImageView之ScaleType详解及拓展

ImageView中有个很重要也很经常使用的属性android:scaleType,相信你们都应该不陌生,主要用于控制图片在ImageView中显示的样式,好比显示大小、显示位置、显示内容区域。固然也能够在代码中设置: setScaleType(ImageView.ScaleType.xxx); ScaleType的取值一共有8种:fitCenterfitEndcentercenterCropcenterInsidematrixfitXYfitStart。其中默认值是fitCenter。 咱们先来看比较简单的center吧,一个60dp*40dp的ImageView(为了显示效果,背景设成蓝色)里面放了张20dp*20dp的图片。上图看看效果:java

center的含义是:保持原图的大小,显示在ImageView的中心。当原图的size大于ImageView的size,超过部分裁剪处理。 再来看比较“暴力”的fitXYandroid

fitXY的含义:拉伸显示图片,不保持原比例,填满ImageView.嗯,果真很暴力。canvas

嗯,接下来咱们...什么?难道你觉得我要把剩下的6种样式都贴张图出来,而后愉快地水一篇博客吗? ide

因此接下来我放大招了,开始分析源码!工具

详解

上面设置了这么多种ScaleType,那么最终生效的位置在哪呢?答案就在 configureBounds()方法里,限于篇幅我贴了上面两种样式的法,其余的样式实现也都相似。post

private void configureBounds() {
        //图片宽高
        final int dwidth = mDrawableWidth;
        final int dheight = mDrawableHeight;
         //Imageview宽高
        final int vwidth = getWidth() - mPaddingLeft - mPaddingRight;//
        final int vheight = getHeight() - mPaddingTop - mPaddingBottom;

        final boolean fits = (dwidth < 0 || vwidth == dwidth)
                && (dheight < 0 || vheight == dheight);

        if (dwidth <= 0 || dheight <= 0 || ScaleType.FIT_XY == mScaleType) {
         
            mDrawable.setBounds(0, 0, vwidth, vheight);
            mDrawMatrix = null;
        } else {
            mDrawable.setBounds(0, 0, dwidth, dheight);
             if (ScaleType.MATRIX == mScaleType) {//样式应用自定义MATRIX
                if (mMatrix.isIdentity()) {
                    mDrawMatrix = null;
                } else {
                    mDrawMatrix = mMatrix;
                }
            } 
         if (ScaleType.CENTER == mScaleType) {
                // Center bitmap in view, no scaling.
                mDrawMatrix = mMatrix;
                mDrawMatrix.setTranslate(Math.round((vwidth - dwidth) * 0.5f),
                                         Math.round((vheight - dheight) * 0.5f));
            } 

复制代码

能够看到最终的实现用到了Drawable类和Matrix类的方法。前者你们都很熟悉,就是咱们设置的要显示的图片,而Matrix叫作矩阵,是一个专门用来处理图形变换中的重要工具类,熟悉自定义View的同窗应该对它不陌生,canvas.setMatrix(matrix)能够作出不少独特效果来。而咱们今天的主角是ImageView,因此没错imageView也有这个方法:spa

imageView.setImageMatrix(matrix)

经过上述方法咱们就能将本身定义的Matrix应用到ImageView中。能够看到源码,要使这个方法生效,ScaleType必定要设为MATRIX,否则执行完本身的变换后仍是会执行样式本身的变换,至关于没执行。code

FIT_XY的实现很简单,就用到了setBounds(int left, int top, int right, int bottom),这个四参数指的是drawable的绘制区域。 center用到了postTranslate(float dx, float dy),将Drawable移到ImageView中间,由于没有其余处理,图片若是比ImageView大,那么多余的区域就会被裁剪掉,不显示了。cdn

拓展

说了这么多来个小栗子来加深理解吧: 仍是上面那张图片,scaleType设为matrix,咱们再加一个按钮,点击事件以下:blog

int m = 20;
    //平移
    private void onClick(View v) {
        Matrix matrix = new Matrix();
        matrix.postTranslate(m, m);
        imageView.setImageMatrix(matrix);
        m = m + 3;
    }
复制代码

来看看效果:

经过改变postTranslate参数的值咱们就能改变图片在View中绘制的起始位置。 固然不会这么简单。Matrix还有其余方法: postRotate(float degrees, float px, float py)//旋转: 咱们仿照center的处理将图片移到ImageView中心,而后进行旋转:

int m = 20;
    //旋转
    private void onClick(View v) {
       Matrix matrix = new Matrix();
        int width = imageView.getDrawable().getIntrinsicWidth();
        int height = imageView.getDrawable().getIntrinsicHeight();
        final int vwidth = imageView.getWidth();
        final int vheight = imageView.getHeight();
        matrix.setTranslate(Math.round((vwidth - width) * 0.5f),
                Math.round((vheight - height) * 0.5f));
        matrix.postRotate(m, vwidth * 0.5f, vheight * 0.5f);
        imageView.setImageMatrix(matrix);
        m = m + 3;
    }
复制代码

看看效果:

还有一种是错切,将图片的形状改变: void setSkew(float kx, float ky) 实际用到的比较少,就不贴代码了,直接看效果吧:

总结

说了这么多,这篇文章就是给你们介绍了android:scaleType的自定义用法,当遇到Imageview预设的显示模式不能知足咱们现有需求的时候(好比我就遇到原图按照原来的大小居底部显示,若是原图的大小超过了ImageView的大小,那么就剪裁掉多余部分,保留底部,和centerCrop裁剪四周有所不一样),咱们就能够动态设置本身的matrix来自定义显示效果。固然若是你常常要用到这种方式的时候,能够继承Imageview,封装这些自定义样式。

相关文章
相关标签/搜索