chia tỷ lệ hình ảnh trong UIButton thành AspectFit?


94

Tôi muốn thêm hình ảnh vào UIButton và cũng muốn chia tỷ lệ hình ảnh của mình để vừa với UIButton (thu nhỏ hình ảnh). Vui lòng chỉ cho tôi cách làm.

Đây là những gì tôi đã thử, nhưng nó không hoạt động:

  • Thêm hình ảnh vào nút và sử dụng setContentMode:
[self.itemImageButton setImage:stretchImage forState:UIControlStateNormal];
[self.itemImageButton setContentMode:UIViewContentModeScaleAspectFit];
  • Tạo một "hình ảnh kéo dài":
UIImage *stretchImage = [updatedItem.thumbnail stretchableImageWithLeftCapWidth:0 topCapHeight:0];

Tôi nghĩ rằng điều này đã được thay đổi thành hành vi mặc định trong phần sụn 4.0 trở lên.
Shaun Budhram

1
Xem stackoverflow.com/a/28205566/481207 để biết giải pháp.
Matt,

Câu trả lời:


28

Nếu bạn thực sự muốn chia tỷ lệ hình ảnh, hãy làm điều đó, nhưng bạn nên thay đổi kích thước trước khi sử dụng. Thay đổi kích thước nó trong thời gian chạy sẽ chỉ làm mất chu kỳ CPU.

Đây là danh mục tôi đang sử dụng để chia tỷ lệ hình ảnh:

UIImage + Extra.h

@interface UIImage (Extras)
- (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize;
@end;

UIImage + Extra.m

@implementation UIImage (Extras)

- (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize {

UIImage *sourceImage = self;
UIImage *newImage = nil;

CGSize imageSize = sourceImage.size;
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;

CGFloat targetWidth = targetSize.width;
CGFloat targetHeight = targetSize.height;

CGFloat scaleFactor = 0.0;
CGFloat scaledWidth = targetWidth;
CGFloat scaledHeight = targetHeight;

CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

if (!CGSizeEqualToSize(imageSize, targetSize)) {

        CGFloat widthFactor = targetWidth / width;
        CGFloat heightFactor = targetHeight / height;

        if (widthFactor < heightFactor) 
                scaleFactor = widthFactor;
        else
                scaleFactor = heightFactor;

        scaledWidth  = width * scaleFactor;
        scaledHeight = height * scaleFactor;

        // center the image

        if (widthFactor < heightFactor) {
                thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; 
        } else if (widthFactor > heightFactor) {
                thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
        }
}


// this is actually the interesting part:

UIGraphicsBeginImageContextWithOptions(targetSize, NO, 0);

CGRect thumbnailRect = CGRectZero;
thumbnailRect.origin = thumbnailPoint;
thumbnailRect.size.width  = scaledWidth;
thumbnailRect.size.height = scaledHeight;

[sourceImage drawInRect:thumbnailRect];

newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

if(newImage == nil) NSLog(@"could not scale image");


return newImage ;
}

@end

Bạn có thể sử dụng nó với kích thước bạn muốn. Giống :

[self.itemImageButton setImage:[stretchImage imageByScalingProportionallyToSize:CGSizeMake(20,20)]];

Cảm ơn câu trả lời của bạn, Gcamp. Tôi đã có một phương pháp để thay đổi kích thước theo tỷ lệ. Nhưng tôi vẫn cố gắng tìm cách bảo UIButton làm điều đó cho tôi. Hình ảnh của tôi được tải từ Internet nên tôi không thể thay đổi kích thước nó vào lúc biên dịch. BTW, cảm ơn bạn rất nhiều vì đã phản hồi.
KONG

2
Vì hình ảnh được đặt vào CALayer, được hiển thị và lưu vào bộ nhớ cache bằng Quartz, hiệu suất sẽ không tệ hơn nếu bạn đặt nó ở đó ở kích thước đầy đủ. Dù bằng cách nào, bạn đang thay đổi kích thước ~ 1 lần. Câu trả lời của gcamp quan trọng hơn nhiều nếu bạn liên tục thay đổi kích thước nút hoặc làm những việc khác có thể kích hoạt Quartz để vẽ lại lớp hình ảnh.
Ben Gotow,

có vẻ như chất lượng hình ảnh bị giảm. tôi đang thử nghiệm trên iphone 6 plus. Có đúng không? Tôi cũng có hình 3x.
Khant Thu Linn

Có, nó sẽ, mã này khá cũ. Nó UIGraphicsBeginImageContextthay vì UIGraphicsBeginImageContextWithOptions. Chỉ cần sửa nó.
gcamp

vâng nhưng trong nhiều trường hợp nó không quan trọng nếu bạn mất một vài chu kỳ, vì vậy không có điểm trong làm đầy lên các ram
Radu Simionescu

203

Tôi đã từng gặp vấn đề tương tự. Chỉ cần đặt ContentMode của ImageView bên trong UIButton.

[[self.itemImageButton imageView] setContentMode: UIViewContentModeScaleAspectFit];
[self.itemImageButton setImage:[UIImage imageNamed:stretchImage] forState:UIControlStateNormal];

Hi vọng điêu nay co ich.


14
Đảm bảo rằng bạn đang cài đặt imageView . Tôi cũng không nhận thấy, một chút, rằng tôi vẫn đang sử dụng backgroundImageView và nó không hoạt động cho điều đó.
Alexandre Gomes,

2
Có vẻ như phương pháp này có một số vấn đề khi trạng thái nút được 'đánh dấu'. Hình ảnh sẽ trở lại chế độ tô màu. Bất kỳ ý tưởng?
Yuanfei Zhu

Nó không hoạt động với tôi. Tuy nhiên, tôi làm cho nó hoạt động bằng cách sử dụng [self.itemImageButton setbackgroundImage: [UIImage imageNamed: stretchImage] forState: UIControlStateNormal];
Mickey

3
Điều này đã làm việc cho tôi. Tôi đặt chế độ nội dung như trên. Tuy nhiên, bạn cũng cần đặt cùng một hình ảnh ở trạng thái được đánh dấu để tránh hình ảnh quay về "chế độ lấp đầy". Ví dụ: [imageButton setImage: image forState: UIControlStateHighlighted];
Christopher

1
Bạn có thể làm điều này trong Interface Builder với con đường chính imageView.contentMode, loại Number, và giá trị1
bendytree

107

Không có câu trả lời nào ở đây thực sự phù hợp với tôi, tôi đã giải quyết vấn đề bằng đoạn mã sau:

button.contentMode = UIViewContentModeScaleToFill;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;

Bạn cũng có thể làm điều này trong Trình tạo giao diện.

nhập mô tả hình ảnh ở đây


5
Điều này không cung cấp cho bạn hành vi phù hợp với khía cạnh như OP yêu cầu.
Ortwin Gentz

3
@OrtwinGentz ​​bạn có thể chọn chế độ và đặt Aspect fitthay vì scale to fill.
Daniel

55

Cách dễ nhất để đặt một UIButton imageView theo cách lập trình ở chế độ phù hợp với khía cạnh :

Nhanh

button.contentHorizontalAlignment = .fill
button.contentVerticalAlignment = .fill
button.imageView?.contentMode = .scaleAspectFit

Objective-C

button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
button.imageView.contentMode = UIViewContentModeScaleAspectFit;

Lưu ý: Bạn có thể thay đổi .scaleAspectFit (UIViewContentModeScaleAspectFit) thành .scaleAspectFill (UIViewContentModeScaleAspectFill) để đặt chế độ lấp đầy khía cạnh


20

Tôi đã gặp sự cố với hình ảnh không thay đổi kích thước tương xứng nên cách tôi sửa nó là sử dụng các tấm lót cạnh.

fooButton.contentEdgeInsets = UIEdgeInsetsMake(10, 15, 10, 15);

16

Điều này hiện có thể được thực hiện thông qua các thuộc tính UIButton của IB. Điều quan trọng là đặt hình ảnh của bạn làm nền, nếu không nó sẽ không hoạt động.

nhập mô tả hình ảnh ở đây


14

Mở rộng câu trả lời của Dave, bạn có thể đặt tất cả contentModecác nút imageViewtrong IB mà không cần bất kỳ mã nào, sử dụng Thuộc tính thời gian chạy:

nhập mô tả hình ảnh ở đây

  • 1nghĩa là UIViewContentModeScaleAspectFit,
  • 2có nghĩa là UIViewContentModeScaleAspectFill.

8

Nếu bạn chỉ muốn giảm hình ảnh nút của mình:

yourButton.contentMode = UIViewContentModeScaleAspectFit;
yourButton.imageEdgeInsets = UIEdgeInsetsMake(10, 10, 10, 10);

Đó phải là yourButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
sdsykes

Không thử với .imageView. Nó đang hoạt động mà không khá tốt.
Tulleb

5

1 - xóa văn bản mặc định của Nút (quan trọng)

2 - đặt căn chỉnh như hình ảnh

3 - đặt chế độ nội dung như hình ảnh

nhập mô tả hình ảnh ở đây


Câu trả lời rất hay, anh bạn ... đã giúp tôi rất nhiều. Cảm ơn!
BharathRao

5

Tôi có một phương pháp làm điều đó cho tôi. Phương pháp lấy UIButtonvà làm cho phù hợp với khía cạnh hình ảnh.

-(void)makeImageAspectFitForButton:(UIButton*)button{
    button.imageView.contentMode=UIViewContentModeScaleAspectFit;
    button.contentHorizontalAlignment=UIControlContentHorizontalAlignmentFill;
    button.contentVerticalAlignment=UIControlContentVerticalAlignmentFill;
}

4

Giải pháp rõ ràng nhất là sử dụng Bố cục Tự động . Tôi đã giảm Mức độ ưu tiên kháng nén nội dung của mình UIButtonvà đặt hình ảnh (không phải Hình nền ) thông qua Trình tạo giao diện . Sau đó, tôi đã thêm một số ràng buộc xác định kích thước của nút của tôi (khá phức tạp trong trường hợp của tôi) và nó hoạt động như một sự quyến rũ.


Điều này phù hợp với tôi - nhưng chỉ khi tôi chọn sử dụng "Hình nền", không phải hình ảnh thực tế. Bất cứ điều gì hoạt động! Điều này đã thúc đẩy tôi NUTS.
Andy

Dưới Xcode 6.2 này làm việc cho tôi nhưng cũng giống như @AndrewHeinlein nói, sử dụngBackground Image
RoLYroLLs

3

đảm bảo rằng bạn đã đặt hình ảnh thành thuộc tính Hình ảnh, nhưng không đặt cho Nền


2

Hình nền thực sự có thể được đặt thành tỷ lệ lấp đầy khía cạnh khá dễ dàng. Chỉ cần làm một cái gì đó như thế này trong một lớp con của UIButton:

- (CGRect)backgroundRectForBounds:(CGRect)bounds
{
    // you'll need the original size of the image, you 
    // can save it from setBackgroundImage:forControlState
    return CGRectFitToFillRect(__original_image_frame_size__, bounds);
}

// Utility function, can be saved elsewhere
CGRect CGRectFitToFillRect( CGRect inRect, CGRect maxRect )
{
    CGFloat origRes = inRect.size.width / inRect.size.height;
    CGFloat newRes = maxRect.size.width / maxRect.size.height;

    CGRect retRect = maxRect;

    if (newRes < origRes)
    {
        retRect.size.width = inRect.size.width * maxRect.size.height / inRect.size.height;
        retRect.origin.x = roundf((maxRect.size.width - retRect.size.width) / 2);
    }
    else
    {
        retRect.size.height = inRect.size.height * maxRect.size.width / inRect.size.width;
        retRect.origin.y = roundf((maxRect.size.height - retRect.size.height) / 2);
    }

    return retRect;
}

Điều này không khả thi nếu không có lớp con?
Iulian Onofrei

Câu trả lời này dành riêng cho backgroundImage. Đối với hình ảnh chính, bạn có thể sử dụng imageEdgeInsets.
Andy Poes

Tôi biết, và tôi muốn nếu có thể đạt được điều này mà không cần lớp con.
Iulian Onofrei

Theo như tôi biết, bạn không thể điều chỉnh backgroundImage mà không phân lớp con.
Andy Poes

1

Swift 5.0

 myButton2.contentMode = .scaleAspectFit
 myButton2.contentHorizontalAlignment = .fill
 myButton2.contentVerticalAlignment = .fill

0

Đối với Xamarin.iOS (C #):

    myButton.VerticalAlignment = UIControlContentVerticalAlignment.Fill;
    myButton.HorizontalAlignment = UIControlContentHorizontalAlignment.Fill;
    myButton.ImageView.ContentMode = UIViewContentMode.ScaleAspectFit;

-1

Bạn chỉ cần đặt chế độ nội dung của UIButton imageview cho ba sự kiện. -

[cell.button setImage:[UIImage imageWithData:data] forState:UIControlStateNormal];

[cell.button setImage:[UIImage imageWithData:data] forState:UIControlStateHighlighted];

[cell.imgIcon setImage:[UIImage imageWithData:data] forState:UIControlStateSelected];

Chúng tôi có mã cho ba bcoz sự kiện trong khi đánh dấu hoặc chọn nếu kích thước nút là SQUARE và kích thước hình ảnh là hình chữ nhật thì nó sẽ hiển thị hình ảnh vuông tại thời điểm đánh dấu hoặc chọn.

Tôi chắc chắn nó sẽ làm việc cho bạn.


Bạn không đặt chế độ nội dung, bạn đang đặt hình ảnh. Và chúng không phải là sự kiện, chúng là trạng thái. Bạn đang làm cho một mớ hỗn độn. Điều này hoàn toàn không liên quan đến câu hỏi.
mancosta
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.