आकांक्षा UIImageView पहलू फिट के साथ


79

अपने UIImageView के लिए मैं Aspect Fit (InterfaceBuilder) का चयन करता हूं लेकिन मैं वर्टिकल अलाइनमेंट कैसे बदल सकता हूं?


1
Imageview के ऊपर और नीचे की संपत्ति के साथ प्रयास करें
ऋतिक

तब काम नहीं करता जब आपके पास पहलू फिट सेट हो।
एथन एलन

5
GitHub पर UIImageViewAligned नामक एक परियोजना है जो यह पूरी तरह से करता है।
डैनियल स्टॉर्म

जवाबों:


40

[संपादित करें - यह कोड 2011 से थोड़ा सा साँचा है और सभी में मैंने @ ArtOfWarefare के तौर-तरीकों को शामिल किया है]

आप यह w / UIImageView नहीं कर सकते। मैंने एक साधारण UIView उपवर्ग बनाया MyImageView, जिसमें UIImageView शामिल है। नीचे कोड।

// MyImageView.h
#import <UIKit/UIKit.h>

@interface MyImageView : UIView {
    UIImageView *_imageView;
}

@property (nonatomic, assign) UIImage *image;

@end

तथा

// MyImageView.m

#import "MyImageView.h"

@implementation MyImageView

@dynamic image;

- (id)initWithCoder:(NSCoder*)coder
{
    self = [super initWithCoder:coder];
    if (self) {
        self.clipsToBounds = YES;
        _imageView = [[UIImageView alloc] initWithFrame:self.bounds];
        _imageView.contentMode = UIViewContentModeScaleAspectFill;
        [self addSubview:_imageView];
    }
    return self;
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.clipsToBounds = YES;
        _imageView = [[UIImageView alloc] initWithFrame:self.bounds];
        _imageView.contentMode = UIViewContentModeScaleAspectFill;
        [self addSubview:_imageView];
    }
    return self;
}

- (id)initWithImage:(UIImage *)anImage
{
    self = [self initWithFrame:CGRectZero];
    if (self) {
        _imageView.image = anImage;
        [_imageView sizeToFit];

        // initialize frame to be same size as imageView
        self.frame = _imageView.bounds;        
    }
    return self;
}

// Delete this function if you're using ARC
- (void)dealloc
{
    [_imageView release];
    [super dealloc];
}

- (UIImage *)image
{
    return _imageView.image;
}

- (void)setImage:(UIImage *)anImage
{
    _imageView.image = anImage;
    [self setNeedsLayout];
}

- (void)layoutSubviews
{
    if (!self.image) return;

    // compute scale factor for imageView
    CGFloat widthScaleFactor = CGRectGetWidth(self.bounds) / self.image.size.width;
    CGFloat heightScaleFactor = CGRectGetHeight(self.bounds) / self.image.size.height;

    CGFloat imageViewXOrigin = 0;
    CGFloat imageViewYOrigin = 0;
    CGFloat imageViewWidth;
    CGFloat imageViewHeight;


    // if image is narrow and tall, scale to width and align vertically to the top
    if (widthScaleFactor > heightScaleFactor) {
        imageViewWidth = self.image.size.width * widthScaleFactor;
        imageViewHeight = self.image.size.height * widthScaleFactor;
    }

    // else if image is wide and short, scale to height and align horizontally centered
    else {
        imageViewWidth = self.image.size.width * heightScaleFactor;
        imageViewHeight = self.image.size.height * heightScaleFactor;
        imageViewXOrigin = - (imageViewWidth - CGRectGetWidth(self.bounds))/2;
    }

    _imageView.frame = CGRectMake(imageViewXOrigin,
                                  imageViewYOrigin,
                                  imageViewWidth,
                                  imageViewHeight);
}

- (void)setFrame:(CGRect)frame
{
    [super setFrame:frame];
    [self setNeedsLayout];
}

@end

3
दो छोटी बातों मैं इस काम करने के लिए करना था: 1 - मैं कार्यान्वित initWithCoder(मैं मूल रूप से कॉपी की गई initWithFrameलेकिन प्रतिस्थापित [super initWithFrame:]के साथ [super initWithCoder:]) और 2 - मैं एक लाइन में जोड़ा if (!self.image) return;करने के लिए layoutSubviewsइतना है कि यह अवैध ज्यामिति के साथ दुर्घटना नहीं होता है, तो एक छवि 'isn टी असाइन किया गया जब यह कहा जाता है। इन दो छोटे परिवर्तनों के साथ यह आश्चर्यजनक रूप से काम करता है।
आर्टऑफवर्फ

sidenote: एआरसी के साथ, deallocविधि को हटाना होगा।
रैप्टर

35

अगर स्टोरीबोर्ड का उपयोग कर इसे बाधाओं से प्राप्त किया जा सकता है ...

सबसे पहले वांछित अंतिम फ्रेम / बाधाओं के साथ एक उविवि। UIVM में एक UIImageView जोड़ें। भरने के लिए ContentMode सेट करें। UIImageView फ्रेम को छवि के समान अनुपात बनाएं (यह बाद में किसी भी स्टोरीबोर्ड चेतावनी से बचा जाता है)। मानक बाधाओं का उपयोग करके यूआईवीवाई को पक्ष पिन करें। मानक बाधाओं का उपयोग करके UIView के लिए ऊपर या नीचे (जहाँ आप इसे संरेखित करना चाहते हैं) पिन करें। अंत में UIImageView में एक पहलू अनुपात बाधा जोड़ें (छवि के रूप में सुनिश्चित अनुपात)।


@ मिचेल प्लैट, यह इतना भ्रामक लगता है, इसलिए यह आईओएस 7 में काम नहीं कर सकता है, क्योंकि आपको पहलू अनुपात की आवश्यकता होती है, जो कि आईओएस 8+ में उपलब्ध है? क्या आपके पास कोई उदाहरण कोड है?
06zgür

2
मैंने इसे भी लागू किया है, यह काम करता है। यह भ्रामक लग सकता है क्योंकि समाधान ऑटो लेआउट बाधा सेटअप का वर्णन कर रहा है। अन्य देवों के लिए, मेरे कार्यान्वयन ने वेब से लोड की गई छवियों का उपयोग किया, इसलिए मुझे छवि की चौड़ाई / ऊँचाई के आधार पर क्रमिक रूप से UIImageView पहलू अनुपात को हटाने और फिर से जोड़ना पड़ा।
माइकल डीपिलिप्स

3
मैंने @MichaelPlatt समाधान के साथ UIImageView एक्सटेंशन बनाया। gist.github.com/megimix/d0bbea45bd3e1e4d615fbd5c30b54da7
megimix

15

यदि आप पहले से ही सामग्री मोड ( .scaleAspectFit) का चयन कर चुके हैं तो आगे के संरेखण नियमों को सेट करने का कोई विकल्प नहीं है क्योंकि यह थोड़ा मुश्किल है ।

लेकिन यहाँ इस पर एक समाधान है:

पहले आयामों की गणना करके अपनी स्रोत छवि को स्पष्ट रूप से आकार देने की आवश्यकता है (यदि यह एक UIImageViewसाथ होगा contentMode = .scaleAspectFit)।

extension UIImage {

    func aspectFitImage(inRect rect: CGRect) -> UIImage? {
        let width = self.size.width
        let height = self.size.height
        let aspectWidth = rect.width / width
        let aspectHeight = rect.height / height
        let scaleFactor = aspectWidth > aspectHeight ? rect.size.height / height : rect.size.width / width

        UIGraphicsBeginImageContextWithOptions(CGSize(width: width * scaleFactor, height: height * scaleFactor), false, 0.0)
        self.draw(in: CGRect(x: 0.0, y: 0.0, width: width * scaleFactor, height: height * scaleFactor))

        defer {
            UIGraphicsEndImageContext()
        }

        return UIGraphicsGetImageFromCurrentImageContext()
    }
}

फिर आपको बस अपनी छवि के फ्रेम को पास करके अपनी मूल छवि पर इस फ़ंक्शन को कॉल करने की आवश्यकता है और अपनी UIImageView.imageसंपत्ति को परिणाम असाइन करें । इसके अलावा, सुनिश्चित करें कि आपने अपने इमेज व्यू को contentModeयहां ( या यहां तक ​​कि इंटरफ़ेस बिल्डर में ) सेट किया है!

let image = UIImage(named: "MySourceImage")
imageView.image = image?.aspectFitImage(inRect: imageView.frame)
imageView.contentMode = .left

4

सेटिंग का प्रयास करें:

imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.clipsToBounds = YES;

इसने मेरे लिए काम किया।



2

मुझे पता है कि यह एक पुराना धागा है, लेकिन मुझे लगा कि मैं इंटरफ़ेस बिल्डर में छवि दृश्य के ऊपर से नीचे की ओर आसानी से क्लिप किए गए क्षेत्र को बदलने के लिए जो मैंने किया था, उसे साझा करूँगा, अगर किसी को भी वही समस्या थी जो मैंने किया था। मेरे पास एक UIImageView था जिसने मेरे ViewController के व्यू को भर दिया था, और डिवाइस की स्क्रीन के आकार से स्वतंत्र, शीर्ष को एक जैसा बनाने की कोशिश कर रहा था।

  1. मैंने रेटिना 4 फॉर्म फैक्टर लागू किया (संपादक-> रेटिना 4 फॉर्म फैक्टर लागू करें)।

  2. मैंने ऊंचाई और चौड़ाई को पिन किया।

अब, जब स्क्रीन का आकार बदलता है, तो UIImageView वास्तव में समान आकार होता है, और व्यू कंट्रोलर केवल स्क्रीन के बंद होने पर क्लिप करता है। फ़्रेम की उत्पत्ति 0,0 पर रहती है, इसलिए छवि के नीचे और दाईं ओर क्लिप लगी होती है, ऊपर नहीं।

उम्मीद है की यह मदद करेगा।


1

आप इसे पहले स्केलिंग और फिर आकार देकर कर सकते हैं। यहां उल्लेख करने वाली बात यह है कि मैं ऊंचाई से वातानुकूलित था। मेरा मतलब है, मेरे पास 34px ऊंची और चाहे कितनी भी चौड़ाई की छवि क्यों न हो।

इसलिए, वास्तविक सामग्री की ऊँचाई और दृश्य की ऊँचाई (34 px) के बीच का अनुपात प्राप्त करें और फिर चौड़ाई भी मापें।

यहाँ है कि मैं यह कैसे किया:

CGSize size = [imageView sizeThatFits:imageView.frame.size];

CGSize actualSize;
actualSize.height = imageView.frame.size.height;
actualSize.width = size.width / (1.0 * (size.height / imageView.frame.size.height));

CGRect frame = imageView.frame;
frame.size = actualSize;
[imageView setFrame:frame];

उम्मीद है की यह मदद करेगा।


1

मैं निम्नलिखित समाधान के लिए आया था:

  1. इसके लिए UIImageViewसामग्री मोड सेट करें top:imageView.contentMode = .top
  2. UIImageView सीमा में फिट होने के लिए छवि का आकार बदलें

छवि को लोड और आकार देने के लिए मैं किंगफ़िशर का उपयोग करता हूं :

let size = imageView.bounds.size
let processor = ResizingImageProcessor(referenceSize: size, mode: .aspectFit)
imageView.kf.setImage(with: URL(string: imageUrl), options: [.processor(processor), .scaleFactor(UIScreen.main.scale)])

यह काम करता है लेकिन छवि धुंधली हो जाती है। मैंने इसे डिवाइस स्क्रीन आकार और डिवाइस स्केलिंग फैक्टर का उपयोग करके इसे ठीक किया: प्रोसेसर = रिसाइज़िंगइमेजप्रोसेसर (संदर्भ: देखें: देखें.फिज़ाब, मोड: .aspectFit); imageView.kf.setImage (साथ: url, विकल्प: [। प्रोसेसर (प्रोसेसर), .scaleFactor (UIScreen.main.scale)])
अलेक्जेंडर मैस्लेव

बहुत बढ़िया। धन्यवाद दोस्त। मैं बाएँ संरेखित करना चाहता था और यह काम किया
कुणाल गुप्ता

0

मैंने UIImageView को उप-लिंक करके और सेटआईएमेज को ओवरराइड करके इसे हल किया: विधि। उपवर्ग पहले मूल और आकार के लिए मूल मूल्यों को संग्रहीत करेगा, ताकि यह मूल सेट आकार को एक सीमा बॉक्स के रूप में उपयोग कर सके।

मैं सामग्री मोड को UIViewContentModeAspectFit पर सेट करता हूं। सेटइमेज के अंदर: मैंने छवि की चौड़ाई को ऊँचाई के अनुपात में पकड़ लिया और फिर छवि को उसी अनुपात में फिट करने के लिए छवि दृश्य का आकार बदल दिया। आकार बदलने के बाद, मैंने अपने फ़्रेम गुणों को उसी स्थान पर छवि दृश्य सेट करने के लिए समायोजित किया, जो पहले था, और फिर मैंने सुपर सेटेजेज कहा:।

यह एक छवि दृश्य में परिणत होता है, जिसके फ्रेम को छवि को ठीक से फिट करने के लिए समायोजित किया गया है, इसलिए पहलू फिट काम करता है और छवि दृश्य फ़्रेम गुण छवि दृश्य डालने में भारी उठाने का कार्य कर रहा है जहां इसे समान प्रभाव प्राप्त करना चाहिए।

यहाँ कुछ कोड है जो मैंने उपयोग किया है:

सबसे पहले, और मुझे यह सामान्य रूप से बहुत उपयोगी लगता है, UIView पर एक श्रेणी है जो बाएँ, दाएँ, ऊपर, नीचे, चौड़ाई, ऊँचाई, आदि गुणों के माध्यम से किसी दृश्य पर फ़्रेम गुण सेट करना आसान बनाता है।

UIImageView + FrameAdditions

@interface UIView (FrameAdditions)

@property CGFloat left, right, top, bottom, width, height;
@property CGPoint origin;

@end

@implementation UIView (FrameAdditions)

- (CGFloat)left {
    return self.frame.origin.x;
}

- (void)setLeft:(CGFloat)left {
    self.frame = CGRectMake(left, self.frame.origin.y, self.frame.size.width, self.frame.size.height);
}

- (CGFloat)right {
    return self.frame.origin.x + self.frame.size.width;
}

- (void)setRight:(CGFloat)right {
    self.frame = CGRectMake(right - self.frame.size.width, self.frame.origin.y, self.frame.size.width, self.frame.size.height);
}

- (CGFloat)top {
    return self.frame.origin.y;
}

- (void)setTop:(CGFloat)top {
    self.frame = CGRectMake(self.frame.origin.x, top, self.frame.size.width, self.frame.size.height);
}

- (CGFloat)bottom {
    return self.frame.origin.y + self.frame.size.height;
}

- (void)setBottom:(CGFloat)bottom {
    self.frame = CGRectMake(self.frame.origin.x, bottom - self.frame.size.height, self.frame.size.width, self.frame.size.height);
}

- (CGFloat)width {
    return self.frame.size.width;
}

- (void)setWidth:(CGFloat)width {
    self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, width, self.frame.size.height);
}

- (CGFloat)height {
    return self.frame.size.height;
}

- (void)setHeight:(CGFloat)height {
    self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, height);
}

- (CGPoint)origin {
    return self.frame.origin;
}

- (void)setOrigin:(CGPoint)origin {
    self.frame = CGRectMake(origin.x, origin.y, self.frame.size.width, self.frame.size.height);
}

@end

यह UIImageView का उपवर्ग है। यह पूरी तरह से परीक्षण नहीं है, लेकिन विचार प्राप्त करना चाहिए। यह संरेखण के लिए अपने स्वयं के नए मोड सेट करने के लिए विस्तारित किया जा सकता है।

बॉटमकार्टेडइमेज व्यू

@interface BottomCenteredImageView : UIImageView

@end


@interface BottomCenteredImageView() {
    CGFloat originalLeft;
    CGFloat originalBottom;
    CGFloat originalHeight;
    CGFloat originalWidth;
}

@end

@implementation BottomCenteredImageView

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if(self) {
        [self initialize];
    }
    return self;
}

- (void)awakeFromNib {
    [self initialize];
}

- (void)initialize {
    originalLeft = self.frame.origin.x;
    originalHeight = CGRectGetHeight(self.frame);
    originalWidth = CGRectGetWidth(self.frame);
    originalBottom = self.frame.origin.y + originalHeight;
}

- (void)setImage:(UIImage *)image {
    if(image) {
        self.width = originalWidth;
        self.height = originalHeight;
        self.left = originalLeft;
        self.bottom = originalBottom;

        float myWidthToHeightRatio = originalWidth/originalHeight;
        float imageWidthToHeightRatio = image.size.width/image.size.height;
        if(myWidthToHeightRatio >= imageWidthToHeightRatio) {
            // Calculate my new width
            CGFloat newWidth = self.height * imageWidthToHeightRatio;
            self.width = newWidth;
            self.left = originalLeft + (originalWidth - self.width)/2;
            self.bottom = originalBottom;
        } else {
            // Calculate my new height
            CGFloat newHeight = self.width / imageWidthToHeightRatio;
            self.height = newHeight;
            self.bottom = originalBottom;
        }
        self.contentMode = UIViewContentModeScaleAspectFit;
        [super setImage:image];
    } else {
        [super setImage:image];
    }
}

@end

अपने VC में UIImageView का उपयोग करने के बजाय, नीचे दिए गए CageedImageView का उपयोग करें।
slemke

यह मेरे लिए काम नहीं करता था ... इसने मेरी छवि के पहलू अनुपात से मेल खाने के लिए मेरे विचार के पहलू अनुपात को बदल दिया, जो कि मैं नहीं चाहता था ... उत्तर XJones ने कुछ बदलावों के साथ खूबसूरती से काम किया जो मैंने नोट किया था उसके जवाब के नीचे टिप्पणियाँ।
आर्टऑफवर्फ

0

यदि आपको एस्पेक्टफिट हासिल करने और खाली जगहों से छुटकारा पाने की आवश्यकता है

स्टोरीबोर्ड से अपनी छवि की चौड़ाई की बाधा को दूर करना न भूलें और आनंद लें

वर्ग SelfSizedImageView: UIImageView {

override func layoutSubviews() {
    super.layoutSubviews()

    guard let imageSize = image?.size else {
        return
    }

    let viewBounds = bounds
    let imageFactor = imageSize.width / imageSize.height
    let newWidth = viewBounds.height * imageFactor

    let myWidthConstraint = self.constraints.first(where: { $0.firstAttribute == .width })
    myWidthConstraint?.constant = min(newWidth, UIScreen.main.bounds.width / 3)

    layoutIfNeeded()
}}

-6

स्केल-टू-फिट छवि को संरेखित करने के लिए ऑटो लेआउट का उपयोग करें। UIImageView में स्केल-टू-फिट के बाद उदाहरण संरेखित छवि:

  1. छवि बनाएं रखने वाला UIImageView बनाएं
  2. दाएं, ऊपर, नीचे, चौड़ाई के लिए ऑटो बाधाएं जोड़ें
  3. चित्र सेट करें:
myUIImageView.contentMode = .ScaleAspectFit
myUIImageView.translatesAutoresizingMaskIntoConstraints = false
myUIImageView.image = UIImage(named:"pizza.png")

आपका पहलू फिट स्केल की गई छवि अब UIImageView में सही रूप से संरेखित है

+----------------------------------+
|                           [IMAGE]|
+----------------------------------+

छवि के भीतर अलग तरीके से संरेखित करने के लिए बाधाओं को बदलें।


यह गर्म नहीं है यह काम करता है, यदि आप पहलू फिट का उपयोग कर रहे हैं, तो संरेखण भारी रूप से छवि के वास्तविक आकार पर निर्भर करता है
अभिषेक मौर्य
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.