asked    Honey     2018-10-22       ios       69 view        1 Answer

[SOLVED] List UIButtons in a Grid view without using CollectionView

I'm going to have a squared grid of UIButton objects. Each of these UIButtons is referenced to an unique option and id coming from an array API.

Example of the option API

options =     (
            {
        name = Color;
        "option_id" = 16;
        "product_option_id" = 1324;
        "product_option_value" =             (
                            {
                image = "example.com/image.jpg";
                name = red;
                "option_value_id" = 104;
                price = 0;
                "price_prefix" = "+";
                "product_option_value_id" = 4650;
            },
                            {
                image = "https://www.ishtari.com/image/cache/data/categories/color/Blue-1125.000000x1125.000000_0.jpg";
                name = blue;
                "option_value_id" = 91;
                price = 0;
                "price_prefix" = "+";
                "product_option_value_id" = 4649;
            }
        );

I'm reading API and listing the Array in a UIButtons

else if dict["type"].stringValue == "image" {
                        let imageOptionView = UIView(frame: CGRect(x: 5, y: Y, width: self.optionView.frame.size.width - 10, height: 30))
                        imageOptionView.isUserInteractionEnabled = true
                        self.optionView.addSubview(imageOptionView)
                        imageOptionView.tag = i
                        self.imageId.append("")
                        Y += 30;
                        let productOptionArray : JSON = JSON(dict["product_option_value"].arrayObject!)
                        let imagesArray:NSMutableArray = []
                        var internalY:CGFloat = 0
                        for j in 0..<productOptionArray.count {


                            let img = RadioButton(frame: CGRect(x: 5, y: internalY, width: 30, height: 30))

                            let imgName = productOptionArray[j]["name"].stringValue
                            img.setTitle(imgName, for: .normal)
                            img.setTitleColor(UIColor.black, for: .normal)
                            img.titleLabel?.font = UIFont.init(name: REGULARFONT, size: 13.0)


                            let images = productOptionArray[j]["image"].stringValue
                            let data = NSData(contentsOf: NSURL(string: images)! as URL)

                            img.setImage(UIImage(data: data! as Data), for: .normal)
                            img.titleEdgeInsets = UIEdgeInsetsMake(0, 6, 0, 0)
                            img.addTarget(self, action: #selector(self.onRadioButtonValueChangedAccount), for:.touchUpInside)

                            img.tag = j
                            imageOptionView.addSubview(img)
                            internalY += 40;

                            imagesArray.add(img)

            }   
                var paymentInformationContainerFrame = imageOptionView.frame
                    paymentInformationContainerFrame.size.height = internalY
                    imageOptionView.frame = paymentInformationContainerFrame
                    let imgButton:RadioButton = RadioButton()
                    //imgButton.groupButtons = imagesArray as! [RadioButton]

                    Y += internalY;

However I want them to be listed in a grid view programmatically without the use of CollectionView, how is that possible?

You can see I defined RadioButton class based on UIButton Class. I am using swift 3

EDIT: Found a solution in objective-c here in the forum then I converted it to swift 3 HERE

else if dict["type"].stringValue == "image" {
            let imageOptionView = UIView(frame: CGRect(x: 5, y: Y, width: self.optionView.frame.size.width - 10, height: 30))
            imageOptionView.isUserInteractionEnabled = true
            self.optionView.addSubview(imageOptionView)
            imageOptionView.tag = i
            self.imageId.append("")
            Y += 30;
            let productOptionArray : JSON = JSON(dict["product_option_value"].arrayObject!)
            let imagesArray:NSMutableArray = []
            var internalY:CGFloat = 0

                for j in 0..<productOptionArray.count {
                            var rows: Int = 5
                            var columns: Int = 1
                            for n in 0..<rows {
                                for m in 0..<columns {

                            var frame = CGRect(x: 1 + 45 * n, y: Int(internalY) * m, width: 40, height: 40)

                            var img = RadioButton(frame: frame) as? RadioButton

                            let imgName = productOptionArray[j]["name"].stringValue
                            img?.setTitle(imgName, for: .normal)
                            img?.setTitleColor(UIColor.black, for: .normal)
                            img?.titleLabel?.font = UIFont.init(name: REGULARFONT, size: 13.0)


                            let images = productOptionArray[j]["image"].stringValue
                            let data = NSData(contentsOf: NSURL(string: images)! as URL)
                            img?.setImage(UIImage(data: data! as Data), for: .normal)
                            img?.titleEdgeInsets = UIEdgeInsetsMake(0, 6, 0, 0)
                            img?.addTarget(self, action: #selector(self.onRadioButtonValueChangedAccount), for:.touchUpInside)

                            img?.tag = j + n * columns + m
                            imageOptionView.addSubview(img!)
                            internalY += 40;

                            imagesArray.add(img!)

                        print("images", images)
                        print("imagesArray", imagesArray)
                        }

                            }
                        }

                        var paymentInformationContainerFrame = imageOptionView.frame
                        paymentInformationContainerFrame.size.height = internalY
                        imageOptionView.frame = paymentInformationContainerFrame
                        let imgButton:RadioButton = RadioButton()
                        imgButton.groupButtons = imagesArray as! [RadioButton]

                        Y += internalY;

}

Now I'm getting the buttons in a Grid View however I'm not getting the right values. For example instead of showing 3 views (objects) it's repeating 1 view (object) 5 times while the others aren't showing. Plus the space between this view and next view horizontally (Y) although I changed the value of Y multiple times but not working.

The print results of imageArray and images

images https://example.com/option-1.jpg
imagesArray (
    "<RadioButton: 0x7fdfafce1b00; baseClass = UIButton; frame = (1 0; 40 40); opaque = NO; layer = <CALayer: 0x60400062c660>>",
    "<RadioButton: 0x7fdfafce2e30; baseClass = UIButton; frame = (46 0; 40 40); opaque = NO; layer = <CALayer: 0x600000629700>>",
    "<RadioButton: 0x7fdfafdc1d00; baseClass = UIButton; frame = (91 0; 40 40); opaque = NO; layer = <CALayer: 0x604000629e20>>",
    "<RadioButton: 0x7fdfafd99910; baseClass = UIButton; frame = (136 0; 40 40); opaque = NO; layer = <CALayer: 0x60400062e2a0>>",
    "<RadioButton: 0x7fdfafcdc960; baseClass = UIButton; frame = (181 0; 40 40); opaque = NO; layer = <CALayer: 0x60000062ff40>>"
)
images https://example.com/option-2.jpg
imagesArray (
    "<RadioButton: 0x7fdfafce1b00; baseClass = UIButton; frame = (1 0; 40 40); opaque = NO; layer = <CALayer: 0x60400062c660>>",
    "<RadioButton: 0x7fdfafce2e30; baseClass = UIButton; frame = (46 0; 40 40); opaque = NO; layer = <CALayer: 0x600000629700>>",
    "<RadioButton: 0x7fdfafdc1d00; baseClass = UIButton; frame = (91 0; 40 40); opaque = NO; layer = <CALayer: 0x604000629e20>>",
    "<RadioButton: 0x7fdfafd99910; baseClass = UIButton; frame = (136 0; 40 40); opaque = NO; layer = <CALayer: 0x60400062e2a0>>",
    "<RadioButton: 0x7fdfafcdc960; baseClass = UIButton; frame = (181 0; 40 40); opaque = NO; layer = <CALayer: 0x60000062ff40>>",
    "<RadioButton: 0x7fdfafdccc30; baseClass = UIButton; frame = (1 0; 40 40); opaque = NO; tag = 1; layer = <CALayer: 0x60400063e8a0>>"
)
images https://example.com/option-2.jpg
imagesArray (
    "<RadioButton: 0x7fdfafce1b00; baseClass = UIButton; frame = (1 0; 40 40); opaque = NO; layer = <CALayer: 0x60400062c660>>",
    "<RadioButton: 0x7fdfafce2e30; baseClass = UIButton; frame = (46 0; 40 40); opaque = NO; layer = <CALayer: 0x600000629700>>",
    "<RadioButton: 0x7fdfafdc1d00; baseClass = UIButton; frame = (91 0; 40 40); opaque = NO; layer = <CALayer: 0x604000629e20>>",
    "<RadioButton: 0x7fdfafd99910; baseClass = UIButton; frame = (136 0; 40 40); opaque = NO; layer = <CALayer: 0x60400062e2a0>>",
    "<RadioButton: 0x7fdfafcdc960; baseClass = UIButton; frame = (181 0; 40 40); opaque = NO; layer = <CALayer: 0x60000062ff40>>",
    "<RadioButton: 0x7fdfafdccc30; baseClass = UIButton; frame = (1 0; 40 40); opaque = NO; tag = 1; layer = <CALayer: 0x60400063e8a0>>",
    "<RadioButton: 0x7fdfafde4430; baseClass = UIButton; frame = (46 0; 40 40); opaque = NO; tag = 1; layer = <CALayer: 0x60400063bd00>>"
)
images https://example.com/option-2.jpg
imagesArray (
    "<RadioButton: 0x7fdfafce1b00; baseClass = UIButton; frame = (1 0; 40 40); opaque = NO; layer = <CALayer: 0x60400062c660>>",
    "<RadioButton: 0x7fdfafce2e30; baseClass = UIButton; frame = (46 0; 40 40); opaque = NO; layer = <CALayer: 0x600000629700>>",
    "<RadioButton: 0x7fdfafdc1d00; baseClass = UIButton; frame = (91 0; 40 40); opaque = NO; layer = <CALayer: 0x604000629e20>>",
    "<RadioButton: 0x7fdfafd99910; baseClass = UIButton; frame = (136 0; 40 40); opaque = NO; layer = <CALayer: 0x60400062e2a0>>",
    "<RadioButton: 0x7fdfafcdc960; baseClass = UIButton; frame = (181 0; 40 40); opaque = NO; layer = <CALayer: 0x60000062ff40>>",
    "<RadioButton: 0x7fdfafdccc30; baseClass = UIButton; frame = (1 0; 40 40); opaque = NO; tag = 1; layer = <CALayer: 0x60400063e8a0>>",
    "<RadioButton: 0x7fdfafde4430; baseClass = UIButton; frame = (46 0; 40 40); opaque = NO; tag = 1; layer = <CALayer: 0x60400063bd00>>",
    "<RadioButton: 0x7fdfafde6200; baseClass = UIButton; frame = (91 0; 40 40); opaque = NO; tag = 1; layer = <CALayer: 0x60400062b620>>"
)
images https://example.com/option-2.jpg
imagesArray (
    "<RadioButton: 0x7fdfafce1b00; baseClass = UIButton; frame = (1 0; 40 40); opaque = NO; layer = <CALayer: 0x60400062c660>>",
    "<RadioButton: 0x7fdfafce2e30; baseClass = UIButton; frame = (46 0; 40 40); opaque = NO; layer = <CALayer: 0x600000629700>>",
    "<RadioButton: 0x7fdfafdc1d00; baseClass = UIButton; frame = (91 0; 40 40); opaque = NO; layer = <CALayer: 0x604000629e20>>",
    "<RadioButton: 0x7fdfafd99910; baseClass = UIButton; frame = (136 0; 40 40); opaque = NO; layer = <CALayer: 0x60400062e2a0>>",
    "<RadioButton: 0x7fdfafcdc960; baseClass = UIButton; frame = (181 0; 40 40); opaque = NO; layer = <CALayer: 0x60000062ff40>>",
    "<RadioButton: 0x7fdfafdccc30; baseClass = UIButton; frame = (1 0; 40 40); opaque = NO; tag = 1; layer = <CALayer: 0x60400063e8a0>>",
    "<RadioButton: 0x7fdfafde4430; baseClass = UIButton; frame = (46 0; 40 40); opaque = NO; tag = 1; layer = <CALayer: 0x60400063bd00>>",
    "<RadioButton: 0x7fdfafde6200; baseClass = UIButton; frame = (91 0; 40 40); opaque = NO; tag = 1; layer = <CALayer: 0x60400062b620>>",
    "<RadioButton: 0x7fdfafde8320; baseClass = UIButton; frame = (136 0; 40 40); opaque = NO; tag = 1; layer = <CALayer: 0x60400063c400>>"
)
images https://example.com/option-2.jpg
imagesArray (
    "<RadioButton: 0x7fdfafce1b00; baseClass = UIButton; frame = (1 0; 40 40); opaque = NO; layer = <CALayer: 0x60400062c660>>",
    "<RadioButton: 0x7fdfafce2e30; baseClass = UIButton; frame = (46 0; 40 40); opaque = NO; layer = <CALayer: 0x600000629700>>",
    "<RadioButton: 0x7fdfafdc1d00; baseClass = UIButton; frame = (91 0; 40 40); opaque = NO; layer = <CALayer: 0x604000629e20>>",
    "<RadioButton: 0x7fdfafd99910; baseClass = UIButton; frame = (136 0; 40 40); opaque = NO; layer = <CALayer: 0x60400062e2a0>>",
    "<RadioButton: 0x7fdfafcdc960; baseClass = UIButton; frame = (181 0; 40 40); opaque = NO; layer = <CALayer: 0x60000062ff40>>",
    "<RadioButton: 0x7fdfafdccc30; baseClass = UIButton; frame = (1 0; 40 40); opaque = NO; tag = 1; layer = <CALayer: 0x60400063e8a0>>",
    "<RadioButton: 0x7fdfafde4430; baseClass = UIButton; frame = (46 0; 40 40); opaque = NO; tag = 1; layer = <CALayer: 0x60400063bd00>>",
    "<RadioButton: 0x7fdfafde6200; baseClass = UIButton; frame = (91 0; 40 40); opaque = NO; tag = 1; layer = <CALayer: 0x60400062b620>>",
    "<RadioButton: 0x7fdfafde8320; baseClass = UIButton; frame = (136 0; 40 40); opaque = NO; tag = 1; layer = <CALayer: 0x60400063c400>>",
    "<RadioButton: 0x7fdfafdea760; baseClass = UIButton; frame = (181 0; 40 40); opaque = NO; tag = 1; layer = <CALayer: 0x60400062f760>>"
)

  1 Answer  

        answered    Murphy     2018-10-22      

If you don't want to use a collection view you can use a vertical stack view containing multiple horizontal stack views, or you could use a scroll view (if you want them to be scrollable) or a containing UIView and custom layout code.

Note that it is possible to evenly space fixed numbers of views using constraints that set the center position of each view as a fraction of the width/height of it's container view

For x position, you'd set the horizontal center constraint to be:

center = (width / (number_of_views + 1) * (view_index + 1)

So if there were 3 views, the horizontal center of your first view, view 0, would be:

center = (width/4) * (0 + 1)

or

center = width/4

So you'd make the center position of the left-most view relative to the width of the superview, with a multiplier of 0.25. Apply the same formula to all of your views in the grid, the x and y dimension.





Your Answer





 2018-10-22         Gabrielle

How do I use Laravel Eloquent to query an object based on an attribute/accessor condition?

Working with the examples from the documentation, if I have a accessor attribute like this:public function getFullNameAttribute(){ return "{$this->first_name} {$this->last_name}"; // both are real columns}How can I run a where based on a computed value? Something like:$user = User::where('full_name', 'John Doe');It should match items where first_name is John and last_name is Doe.Is there a way to do this or am I doing it wrong?Update: I found a similar question asked for Laravel 4 and it has an answer, however it states that the filtering is applied after the query...
 database                     2 answers                     48 view
 2018-10-22         Lindsay

Laravel Belongsto many relationship with additional column

I have been facing a problem in my project. I have a belongsto many relation with additional field.For example I have two table User and Social table and a pivot table named social_user. Here my user model ispublic function socialinfos() { return $this->belongsToMany(Social::class)->withPivot('id')->whereNull('deleted_at');}And my social_user table is Schema::create('social_user', function (Blueprint $table) { $table->bigIncrements('id'); $table->bigInteger('user_id'); $table->string('social_id')->nullable(); $table->string('url')->...
 php                     1 answers                     50 view
 2018-10-22         Antony

laravel replicate() method and computed database column

I'm trying to copy a row using by replicate() method:$doc = Doc::find(64618);$newdoc = $doc->replicate();$newdoc->Price= 9999; $newdoc->save();but this table contains several computed columns and I get an error that the data fields can not be updated.How can I exclude these fields when using replicate()? You can pass the columns that you want to excludes$doc = Doc::find(64618);$newdoc = $doc->replicate(['column1', 'column2']);$newdoc->Price= 9999; $newdoc->save();Here is the source you will find out if u deep dive into the core./** * Clone the model...
 laravel                     1 answers                     51 view