skala Gambar di UIButton ke AspectFit?


94

Saya ingin menambahkan gambar ke UIButton, dan juga ingin menskalakan gambar saya agar sesuai dengan UIButton (membuat gambar lebih kecil). Tolong tunjukkan bagaimana melakukannya.

Inilah yang telah saya coba, tetapi tidak berhasil:

  • Menambahkan gambar ke tombol dan menggunakan setContentMode:
[self.itemImageButton setImage:stretchImage forState:UIControlStateNormal];
[self.itemImageButton setContentMode:UIViewContentModeScaleAspectFit];
  • Membuat "gambar peregangan":
UIImage *stretchImage = [updatedItem.thumbnail stretchableImageWithLeftCapWidth:0 topCapHeight:0];

Saya rasa ini telah diubah menjadi perilaku default di firmware 4.0 dan yang lebih baru.
Shaun Budhram

1
Lihat stackoverflow.com/a/28205566/481207 untuk solusinya.
Matt

Jawaban:


28

Jika Anda benar-benar ingin menskalakan gambar, lakukan, tetapi Anda harus mengubah ukurannya sebelum menggunakannya. Mengubah ukurannya pada waktu proses hanya akan kehilangan siklus CPU.

Ini adalah kategori yang saya gunakan untuk menskalakan gambar:

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

Anda dapat menggunakannya sesuai ukuran yang Anda inginkan. Suka :

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

Terima kasih atas jawaban Anda, Gcamp. Saya memang memiliki metode untuk mengubah ukuran dengan rasio. Tetapi saya masih mencoba menemukan cara untuk memberi tahu UIButton melakukannya untuk saya. Gambar saya dimuat dari Internet jadi saya tidak dapat mengubah ukurannya pada waktu kompilasi. BTW, terima kasih banyak atas tanggapan Anda.
KONG

2
Karena gambar ditempatkan ke dalam CALayer, dirender, dan disimpan dalam cache oleh Quartz, performa seharusnya tidak lebih buruk jika Anda menempatkannya di sana dalam ukuran penuh. Apa pun itu, Anda mengubah ukuran ~ 1 kali. Jawaban gcamp jauh lebih penting jika Anda terus-menerus mengubah ukuran tombol atau melakukan hal lain yang akan memicu Quartz untuk menggambar ulang lapisan gambar.
Ben Gotow

sepertinya kualitas gambar berkurang. saya sedang menguji pada iphone 6 plus. Benarkah Saya juga memiliki gambar 3x.
Khant Thu Linn

Ya itu akan, kode ini cukup tua. Itu UIGraphicsBeginImageContextbukan UIGraphicsBeginImageContextWithOptions. Perbaiki saja.
gcamp

ya tetapi dalam banyak kasus tidak masalah jika Anda kehilangan beberapa siklus, jadi tidak ada gunanya mengisi ram
Radu Simionescu

203

Saya memiliki masalah yang sama. Cukup setel ContentMode dari ImageView yang ada di dalam UIButton.

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

Semoga ini membantu.


14
Pastikan Anda menyetel imageView . Saya juga gagal memperhatikan, untuk sedikit, bahwa saya masih menggunakan backgroundImageView dan tidak berfungsi untuk itu.
Alexandre Gomes

2
Tampaknya metode ini memiliki beberapa masalah ketika status tombol 'disorot'. Gambar akan kembali ke mode isian. Ada ide?
Yuanfei Zhu

Itu tidak berhasil bagi saya. Namun, saya membuatnya bekerja dengan menggunakan [self.itemImageButton setbackgroundImage: [UIImage imageNamed: stretchImage] forState: UIControlStateNormal];
Mickey

3
Ini berhasil untuk saya. Saya mengatur mode konten seperti di atas. Namun, Anda juga perlu menyetel gambar yang sama dari status yang disorot untuk menghindari gambar kembali ke "mode isi". Misalnya, [imageButton setImage: image forState: UIControlStateHighlighted];
Christopher

1
Anda dapat melakukan ini di Interface Builder dengan jalur kunci imageView.contentMode, jenis Number, dan nilai1
bendytree

107

Tidak ada jawaban di sini yang benar-benar berhasil untuk saya, saya memecahkan masalah dengan kode berikut:

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

Anda juga dapat melakukan ini di Interface Builder.

masukkan deskripsi gambar di sini


5
Ini tidak memberi Anda perilaku aspek fit seperti yang diminta oleh OP.
Ortwin Gentz

3
@OrtwinGentz Anda dapat memilih mode dan set Aspect fitbukan scale to fill.
Daniel

55

Cara termudah untuk menyetel UIButton imageView secara terprogram dalam mode penyesuaian aspek :

Cepat

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

Objective-C

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

Catatan: Anda dapat mengubah .scaleAspectFit (UIViewContentModeScaleAspectFit) menjadi .scaleAspectFill (UIViewContentModeScaleAspectFill) untuk menyetel mode pengisian aspek


20

Saya memiliki masalah dengan gambar yang tidak mengubah ukuran secara proporsional sehingga cara saya memperbaikinya menggunakan sisipan tepi.

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

16

Ini sekarang dapat dilakukan melalui properti UIButton IB. Kuncinya adalah mengatur gambar Anda sebagai latar belakang, jika tidak maka tidak akan berhasil.

masukkan deskripsi gambar di sini


14

Memperluas jawaban Dave, Anda dapat mengatur contentModesemua tombol imageViewdi IB, tanpa kode apa pun, menggunakan Runtime Attributes:

masukkan deskripsi gambar di sini

  • 1artinya UIViewContentModeScaleAspectFit,
  • 2akan berarti UIViewContentModeScaleAspectFill.

8

Jika Anda hanya ingin mengurangi gambar tombol Anda:

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

Itu seharusnya yourButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
sdsykes

Tidak mencoba dengan .imageView. Ini bekerja tanpa cukup baik.
Tulleb

5

1 - Hapus teks default tombol (penting)

2 - atur perataan seperti gambar

3 - atur mode konten seperti gambar

masukkan deskripsi gambar di sini


Jawaban yang bagus bro..banyak membantu saya. Terima kasih!
BharathRao

5

Saya memiliki metode yang melakukannya untuk saya. Metode tersebut mengambil UIButtondan membuat aspek gambar sesuai.

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

4

Solusi terbersih adalah dengan menggunakan Tata Letak Otomatis . Saya menurunkan Prioritas Resistensi Kompresi Konten saya UIButtondan mengatur gambar (bukan Gambar Latar Belakang ) melalui Pembuat Antarmuka . Setelah itu saya menambahkan beberapa batasan yang menentukan ukuran tombol saya (cukup rumit dalam kasus saya) dan itu bekerja seperti pesona.


Ini berhasil untuk saya - tetapi hanya jika saya memilih untuk menggunakan "Gambar Latar Belakang", bukan gambar sebenarnya. Apapun yang berhasil! Ini membuat saya NUTS.
Andy

Di bawah Xcode 6.2 ini berhasil untuk saya tetapi seperti yang dikatakan @AndrewHeinlein, digunakanBackground Image
RoLYroLLs

3

pastikan Anda telah menyetel gambar ke properti Image, tetapi tidak ke Background


2

Gambar latar belakang sebenarnya dapat diatur ke isi skala dengan cukup mudah. Hanya perlu melakukan sesuatu seperti ini di subclass 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;
}

Bukankah ini mungkin tanpa subclass?
Iulian Onofrei

Jawaban ini khusus untuk backgroundImage. Untuk gambar utama Anda bisa monyet dengan imageEdgeInsets.
Andy Poes

Saya tahu, dan saya ingin jika mungkin untuk mencapai ini tanpa subclass.
Iulian Onofrei

Sejauh yang saya tahu, Anda tidak dapat menyesuaikan backgroundImage tanpa subclassing.
Andy Poes

1

Swift 5.0.0

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

0

Untuk Xamarin.iOS (C #):

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

-1

Anda hanya perlu menyetel mode konten UIButton imageview untuk tiga acara. -

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

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

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

Kami memiliki kode untuk tiga acara bcoz saat menyorot atau memilih jika ukuran tombol adalah KOTAK dan ukuran gambar persegi panjang maka itu akan menampilkan gambar persegi pada saat menyorot atau memilih.

Saya yakin ini akan berhasil untuk Anda.


Anda tidak menyetel mode konten, Anda sedang menyetel gambar. Dan itu bukan acara, itu negara bagian. Anda membuat kekacauan besar. Ini sama sekali tidak terkait dengan pertanyaan itu.
manecosta
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.