首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ImageView scaling TOP_CROP

ImageView scaling TOP_CROP
EN

Stack Overflow用户
提问于 2011-06-13 19:56:56
回答 11查看 44.8K关注 0票数 92

我有一个ImageView,它显示的png的纵横比比设备的要大(垂直地说-意味着它更长)。我想要在保持纵横比的同时显示,匹配父对象的宽度,并将图像视图固定在屏幕顶部。

我使用CENTER_CROP作为缩放类型的问题是,它会(可以理解)将缩放的图像居中,而不是将顶部边缘与图像视图的顶部边缘对齐。

FIT_START的问题是图像将适合屏幕高度,而不是填充宽度。

我已经解决了这个问题,我使用一个自定义的ImageView,覆盖onDraw(Canvas),并使用画布手动处理这个问题;这种方法的问题是: 1)我担心可能有更简单的解决方案,2)当尝试在构造函数中调用super(AttributeSet)时,当尝试设置330kb的src img时,当堆有3mb的空闲空间(堆大小为6mb)时,我得到了VM mem异常,但找不出原因。

非常欢迎任何想法/建议/解决方案:)

谢谢

附注:我认为一个解决方案可能是使用矩阵缩放类型并自己做,但这似乎与我目前的解决方案相同或更多的工作!

EN

回答 11

Stack Overflow用户

回答已采纳

发布于 2011-06-14 00:47:14

好的,我有一个可行的解决方案。Darko的提示让我再次查看了ImageView类(谢谢),并使用矩阵应用了转换(正如我最初怀疑的那样,但在第一次尝试中没有成功!)。在我的自定义imageView类中,我在构造函数中的super()之后调用setScaleType(ScaleType.MATRIX),并具有以下方法。

代码语言:javascript
复制
    @Override
    protected boolean setFrame(int l, int t, int r, int b)
    {
        Matrix matrix = getImageMatrix(); 
        float scaleFactor = getWidth()/(float)getDrawable().getIntrinsicWidth();    
        matrix.setScale(scaleFactor, scaleFactor, 0, 0);
        setImageMatrix(matrix);
        return super.setFrame(l, t, r, b);
    }

我将int放在setFrame()方法中,就像在ImageView中一样,对configureBounds()的调用在这个方法中,这是所有缩放和矩阵工作发生的地方,所以对我来说似乎是合乎逻辑的(如果你不同意的话)。

下面是来自安卓开源项目的super.setFrame()方法

代码语言:javascript
复制
    @Override
    protected boolean setFrame(int l, int t, int r, int b) {
        boolean changed = super.setFrame(l, t, r, b);
        mHaveFrame = true;
        configureBounds();
        return changed;
    }

查找完整的类src here

票数 86
EN

Stack Overflow用户

发布于 2012-07-23 03:17:15

下面是我在底部居中显示的代码。

顺便说一句,Dori的代码中有一个小错误:因为super.frame()是在最后调用的,所以getWidth()方法可能会返回错误的值。

如果您想将它放在顶部居中,只需删除postTranslate行,就完成了。

好的是,使用此代码,您可以将其移动到您想要的任何位置。(对,中锋=>没问题;)

代码语言:javascript
复制
    public class CenterBottomImageView extends ImageView {
    
        public CenterBottomImageView(Context context) {
            super(context);
            setup();
        }
        
        public CenterBottomImageView(Context context, AttributeSet attrs) {
            super(context, attrs);
            setup();
        }
    
        public CenterBottomImageView(Context context, AttributeSet attrs,
                int defStyle) {
            super(context, attrs, defStyle);
            setup();
        }
        
        private void setup() {
            setScaleType(ScaleType.MATRIX);
        }
    
        @Override
        protected boolean setFrame(int frameLeft, int frameTop, int frameRight, int frameBottom) {
            if (getDrawable() == null) {
                return super.setFrame(frameLeft, frameTop, frameRight, frameBottom);
            }
            float frameWidth = frameRight - frameLeft;
            float frameHeight = frameBottom - frameTop;
            
            float originalImageWidth = (float)getDrawable().getIntrinsicWidth();
            float originalImageHeight = (float)getDrawable().getIntrinsicHeight();
            
            float usedScaleFactor = 1;
            
            if((frameWidth > originalImageWidth) || (frameHeight > originalImageHeight)) {
                // If frame is bigger than image
                // => Crop it, keep aspect ratio and position it at the bottom and center horizontally
                
                float fitHorizontallyScaleFactor = frameWidth/originalImageWidth;
                float fitVerticallyScaleFactor = frameHeight/originalImageHeight;
                
                usedScaleFactor = Math.max(fitHorizontallyScaleFactor, fitVerticallyScaleFactor);
            }
            
            float newImageWidth = originalImageWidth * usedScaleFactor;
            float newImageHeight = originalImageHeight * usedScaleFactor;
            
            Matrix matrix = getImageMatrix();
            matrix.setScale(usedScaleFactor, usedScaleFactor, 0, 0); // Replaces the old matrix completly
//comment matrix.postTranslate if you want crop from TOP
            matrix.postTranslate((frameWidth - newImageWidth) /2, frameHeight - newImageHeight);
            setImageMatrix(matrix);
            return super.setFrame(frameLeft, frameTop, frameRight, frameBottom);
        }
    
    }

初学者提示:如果它不能正常工作,你可能不得不使用extends androidx.appcompat.widget.AppCompatImageView而不是ImageView

票数 45
EN

Stack Overflow用户

发布于 2016-06-27 16:40:21

您无需编写自定义图像视图即可获取TOP_CROP功能。您只需要修改ImageViewmatrix即可。

  1. ImageViewscaleType设置为matrix
票数 40
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6330084

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档