9宫格算法 ios

2015-09-13 19:37:38 ning_ya9293 阅读数 6501

九宫格的算法分析:

Tables Are Cool
0 1 2
3 4 5
6 7 8

格子间: 间隙 = (控制器view的宽度 - 3 * 应用宽度) / 4
index 表示格子的索引,即0,1,2,3……8
for(index= 0;index < 9 ; index++)
计算行号:int row = index / 3 ; 决定y
计算列号:int col = index % 3;决定x

//算法实例:
int margin = 30;//间隙
int width = 80;//格子的宽
int height = 80;//格子的高

for (int i = 0; i <9; i++) {
    int row = i/3;
    int col = i%3;
    UILabel * label = [[UILabel alloc]init];
    label.frame = CGRectMake(20+col*(width+margin), 40+row*(height+margin), width, height);
    label.backgroundColor = [UIColor redColor];
    [self.view addSubview:label];
}
2019-04-23 16:47:58 uratio 阅读数 241

注:用的切图和标注全是用的IOS的,以750*1334的尺寸进行标注的

自定义的 九宫格控件 LotteryView :

package com.uratio.demop.lottery;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.os.SystemClock;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.uratio.demop.utils.DensityUtils;

import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class LotteryView extends SurfaceView implements SurfaceHolder.Callback {
    private Context context;
    /**
     * holder
     */
    private SurfaceHolder mHolder;


    private List<Prize> prizes;
    private boolean flags;

    private int lottery = 6; //设置中奖号码

    private int current = 2; //抽奖开始的位置

    private int count = 0; //旋转次数累计

    private int countDown; //倒计次数,快速旋转完成后,需要倒计多少次循环才停止

    private int transfer = 0x30000000;//中奖背景

    private int MAX = 50; //最大旋转次数

    private OnTransferWinningListener listener;

    private Bitmap bmBg;

    private int bgColor;

    private Bitmap bmChoose;

    private Bitmap bmPrizeBg;

    private int paddingSize = 22;//内部padding值

    private int itemSpace = 8;//item的间距

    private int paddingSizeRadio = 75;//内部padding原始尺寸比例

    private int itemSpaceRadio = 25;//item的间距原始尺寸比例

    private int imageMarginLRRadio = 20;//奖品图片距左右原始尺寸比例

    private int imageMarginTBRadio = 24;//奖品图片距上下原始尺寸比例

    private int itemRulerWidth = 90;//item的宽度原始尺寸比例

    private int rulerWidth = 690;//抽奖背景原始尺寸比例

    public void setOnTransferWinningListener(OnTransferWinningListener listener) {
        this.listener = listener;
    }

    public interface OnTransferWinningListener {
        /**
         * 点击开始抽奖
         */
        void onClickStart();

        /**
         * 中奖回调
         *
         * @param position
         */
        void onWinning(int position);
    }


    /**
     * 设置中奖号码
     *
     * @param lottery
     */
    public void setLottery(int lottery) {
        if (prizes != null && Math.round(prizes.size() / 2) == 0) {
            throw new RuntimeException("开始抽奖按钮不能设置为中奖位置!");
        }
        this.lottery = lottery;
    }

    /**
     * 设置中奖颜色
     *
     * @param transfer
     */
    public void setTransfer(int transfer) {
        this.transfer = transfer;
    }

    public void setPaddingSizeRadio(int paddingSizeRadio) {
        this.paddingSizeRadio = paddingSizeRadio;
        paddingSize = getMeasuredWidth() * paddingSizeRadio / 2 / rulerWidth;
    }

    public void setItemSpaceRadio(int itemSpaceRadio) {
        this.itemSpaceRadio = itemSpaceRadio;
        itemSpace = getMeasuredWidth() * itemSpaceRadio / 2 / rulerWidth;
    }

    public void setImageMarginLRRadio(int imageMarginLRRadio) {
        this.imageMarginLRRadio = imageMarginLRRadio;
    }

    public void setImageMarginTBRadio(int imageMarginTBRadio) {
        this.imageMarginTBRadio = imageMarginTBRadio;
    }

    public void setItemRulerWidth(int itemRulerWidth) {
        this.itemRulerWidth = itemRulerWidth;
    }

    public void setRulerWidth(int rulerWidth) {
        this.rulerWidth = rulerWidth;
    }

    public void setBmBg(Bitmap bmBg) {
        this.bmBg = bmBg;
    }

    public void setBgColor(int bgColor) {
        this.bgColor = bgColor;
    }

    public void setBmChoose(Bitmap bmChoose) {
        this.bmChoose = bmChoose;
    }

    public void setBmPrizeBg(Bitmap bmPrizeBg) {
        this.bmPrizeBg = bmPrizeBg;
    }

    /**
     * 设置奖品集合
     *
     * @param prizes
     */
    public void setPrizes(List<Prize> prizes) {
        this.prizes = prizes;
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        handleTouch(event);
        return super.onTouchEvent(event);
    }

    /**
     * 触摸
     *
     * @param event
     */
    public void handleTouch(MotionEvent event) {
        int clickX = (int) event.getX();
        int clickY = (int) event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                int startPosition = Math.round(prizes.size() / 2);
                Prize prize = prizes.get(startPosition);

                int width = (getMeasuredWidth() - 2 * paddingSize) / 3;
                int len = (int) Math.sqrt(prizes.size());
                int x1 = getPaddingLeft() + width * (Math.abs(startPosition) % len) + paddingSize + itemSpace;
                int y1 = getPaddingTop() + width * ((startPosition) / len) + paddingSize + itemSpace;

                int x2 = x1 + width - 2 * itemSpace;
                int y2 = y1 + width - 2 * itemSpace;

                if (clickX >= x1 && clickX <= x2 && clickY >= y1 && clickY <= y2){
                    if (!flags) {
                        setStartFlags(true);
                        prize.click();
                    }
                }
                break;
            default:
                break;
        }
    }

    private class SurfaceRunnable implements Runnable {
        @Override
        public void run() {
            while (flags) {
                Canvas canvas = null;
                try {
                    canvas = mHolder.lockCanvas();

                    drawBg(canvas);

                    drawPrize(canvas);

                    drawTransfer(canvas);

                    controllerTransfer();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (canvas != null)
                        mHolder.unlockCanvasAndPost(canvas);
                }
            }
        }
    }

    //绘制所有奖品背景
    private void drawBg(Canvas canvas) {
        canvas.drawColor(Color.WHITE, PorterDuff.Mode.CLEAR);
        //分块画背景
        int width = getMeasuredWidth() / 3;
        int x1 = 0;
        int y1 = 0;

        int x2 = 0;
        int y2 = 0;

        int len = (int) Math.sqrt(prizes.size());

        /*for(int x=0;x<len*len;x++){

            Prize prize = prizes.get(x);

            int index=x;
            x1=getPaddingLeft()+width*(Math.abs(index)%len);
            y1=getPaddingTop()+width*(index/len);

            x2=x1+width;
            y2=y1+width;
            Rect rect=new Rect(x1,y1,x2,y2);

            Paint paint=new Paint();
            paint.setColor(prize.getBgColor());
            canvas.drawRect(rect, paint);
        }*/
        //使用图片背景
        x1 = getPaddingLeft();
        y1 = getPaddingTop();
        x2 = x1 + getMeasuredWidth();
        y2 = y1 + getMeasuredWidth();
        Rect rect = new Rect(x1, y1, x2, y2);
        Paint paint = new Paint();
        paint.setColor(bgColor);
        canvas.drawRect(rect, paint);
        canvas.drawBitmap(bmBg, null, rect, paint);
    }

    //绘制旋转的奖品背景
    private void drawTransfer(Canvas canvas) {
        int width = (getMeasuredWidth() - 2 * paddingSize) / 3;
        int x1;
        int y1;

        int x2;
        int y2;
        int len = (int) Math.sqrt(prizes.size());
        current = next(current, len);
        x1 = getPaddingLeft() + width * (Math.abs(current) % len) + paddingSize + itemSpace;
        y1 = getPaddingTop() + width * ((current) / len) + paddingSize + itemSpace;

        x2 = x1 + width - 2 * itemSpace;
        y2 = y1 + width - 2 * itemSpace;

        Rect rect = new Rect(x1, y1, x2, y2);
        //颜色选择背景
//        Paint paint=new Paint();
//        paint.setColor(transfer);
//        canvas.drawRect(rect, paint);
        //图片选择背景
        canvas.drawBitmap(bmChoose, null, rect, null);
    }

    //控制旋转的速度
    private void controllerTransfer() {
        if (count > MAX) {
            countDown++;
            SystemClock.sleep(count * 5);
        } else {
            SystemClock.sleep(count * 2);
        }

        count++;
        if (countDown > 2) {
            if (lottery == current) {
                countDown = 0;
                count = 0;
                setStartFlags(false);
                if (listener != null) {
                    //切换到主线程中运行
                    post(new Runnable() {
                        @Override
                        public void run() {
                            listener.onWinning(current);
                        }
                    });

                }
            }
        }
    }

    public void setStartFlags(boolean flags) {
        this.flags = flags;
    }

    //绘制奖品背景
    private void drawPrize(Canvas canvas) {
        int width = (getMeasuredWidth() - 2 * paddingSize) / 3;
        int x1 = 0;
        int y1 = 0;

        int x2 = 0;
        int y2 = 0;

        int len = (int) Math.sqrt(prizes.size());

        for (int x = 0; x < len * len; x++) {

            Prize prize = prizes.get(x);

            int index = x;
            x1 = getPaddingLeft() + width * (Math.abs(index) % len) + paddingSize + itemSpace;
            y1 = getPaddingTop() + width * (index / len) + paddingSize + itemSpace;

            x2 = x1 + width - 2 * itemSpace;
            y2 = y1 + width - 2 * itemSpace;
            //奖品背景
            Rect rectBg = new Rect(x1, y1, x2, y2);
//            canvas.drawBitmap(bmPrizeBg, null, rectBg, null);
            if (x == (prizes.size() - 1) / 2) {
                canvas.drawBitmap(prize.getIcon(), null, rectBg, null);
            } else {
                canvas.drawBitmap(bmPrizeBg, null, rectBg, null);
//                //奖品图片
                int itemWidth = x2 - x1;
                int lr = itemWidth * imageMarginLRRadio / DensityUtils.dip2px(context, itemRulerWidth);
                int tb = itemWidth * imageMarginTBRadio / DensityUtils.dip2px(context, itemRulerWidth);

                int itemHeight = y2 - y1;

                Rect rectImg = new Rect(x1 + lr, y1 + tb, x2 - lr, y1 + itemHeight * 5 / 9 - tb);
                canvas.drawBitmap(prize.getIcon(), null, rectImg, null);
//                //奖品文字
                canvas.save();
                canvas.translate(x1, y1 + itemHeight * 5 / 9);
                TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
                textPaint.setColor(prize.getDescColor());

                int size = itemHeight * 11 / DensityUtils.dip2px(context, itemRulerWidth);
                textPaint.setTextSize(DensityUtils.sp2px(context, size));
                StaticLayout staticLayout = new StaticLayout(prize.getDesc(), textPaint, itemWidth, Layout.Alignment.ALIGN_CENTER, 1.2f, 0, true);
                staticLayout.draw(canvas);
                canvas.restore();
            }
        }
    }

    public void start() {
//        setLottery(getRandom());
        ExecutorService service = Executors.newCachedThreadPool();
        service.execute(new SurfaceRunnable());
    }

    //获取随机中奖数,实际开发中一般中奖号码是服务器告诉我们的
    private int getRandom() {
        Random r = new Random();
        int nextInt = r.nextInt(prizes.size());
        if (nextInt % (Math.round(prizes.size() / 2)) == 0) {
            //随机号码等于中间开始位置,需要继续摇随机号
            return getRandom();
        }
        return nextInt;
    }

    //下一步
    public int next(int current, int len) {
        if (current + 1 < len) {
            return ++current;
        }

        if ((current + 1) % len == 0 & current < len * len - 1) {
            return current += len;
        }

        if (current % len == 0) {
            return current -= len;
        }

        if (current < len * len) {
            return --current;
        }

        return current;
    }


    public LotteryView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        mHolder = this.getHolder();
        mHolder.addCallback(this);
    }

    public LotteryView(Context context) {
        this(context, null);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
                               int height) {
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        paddingSize = getMeasuredWidth() * paddingSizeRadio / 2 / rulerWidth;
        itemSpace = getMeasuredWidth() * itemSpaceRadio / 2 / rulerWidth;

        Canvas canvas = null;
        try {
            canvas = mHolder.lockCanvas();
            drawBg(canvas);
            drawPrize(canvas);

            Prize prize = prizes.get(Math.round(prizes.size() / 2));
            prize.setListener(new Prize.OnClickListener() {

                @Override
                public void onClick() {
                    if (listener != null) {
                        listener.onClickStart();
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (canvas != null)
                mHolder.unlockCanvasAndPost(canvas);
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        setStartFlags(false);
    }

    /**
     * 重新测量
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//        int width = Math.min(getMeasuredWidth(), getMeasuredHeight());
        setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth());

    }
}

奖品的Bean类:

package com.uratio.demop.lottery;

import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.Log;

import java.io.Serializable;

public class Prize implements Serializable {
    private int Id;
    private String Name;
    private Bitmap icon;
    private String desc;
    private int bgColor;
    private int descColor;
    private OnClickListener listener;

    @Override
    public String toString() {
        return "Prize{" +
                "Id=" + Id +
                ", Name='" + Name + '\'' +
                ", icon=" + icon +
                ", desc='" + desc + '\'' +
                ", bgColor=" + bgColor +
                ", descColor=" + descColor +
                ", listener=" + listener +
                '}';
    }

    public int getId() {
        return Id;
    }

    public void setId(int id) {
        Id = id;
    }

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    }

    public Bitmap getIcon() {
        return icon;
    }

    public void setIcon(Bitmap icon) {
        this.icon = icon;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public int getBgColor() {
        return bgColor;
    }

    public void setBgColor(int bgColor) {
        this.bgColor = bgColor;
    }

    public int getDescColor() {
        return descColor;
    }

    public void setDescColor(int descColor) {
        this.descColor = descColor;
    }

    public OnClickListener getListener() {
        return listener;
    }

    public void setListener(OnClickListener listener) {
        this.listener = listener;
    }

    public interface OnClickListener {
        void onClick();
    }

    public void click() {
        listener.onClick();
    }
}

尺寸转换工具类:

package com.uratio.demop.utils;

import android.content.Context;
import android.util.TypedValue;

public class DensityUtils {
    /**
     * 根据手机的分辨率从 dip 的单位 转成为 px(像素)
     */
    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    /**
     * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
     */
    public static int px2dip(Context context, float pxValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

    /**
     * 将px值转换为sp值,保证文字大小不变
     */
    public static int px2sp(Context context, float pxValue) {
        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (pxValue / fontScale + 0.5f);
    }

    /**
     * 将sp值转换为px值,保证文字大小不变
     */
    public static int sp2px(Context context, float spValue) {
        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }

    /**
     * 根据手机的分辨率从 dip 的单位 转成为 px(像素)
     */
    public static int dp2px(Context context, int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
    }

    /**
     * 将sp值转换为px值,保证文字大小不变
     */
    public static int sp2px(Context context, int sp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, context.getResources().getDisplayMetrics());
    }
}

activity的xml文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    android:background="#CAF3E5"
    tools:context=".lottery.LotteryActivity">
    <TextView
        android:id="@+id/tv_integral"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:textSize="20sp"
        android:textColor="#ff3f2f"/>

    <com.uratio.demop.lottery.LotteryView
        android:id="@+id/nl"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="30px"/>
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="1px"/>
</LinearLayout>

activity内容:

package com.uratio.demop.lottery;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

import com.uratio.demop.R;

import java.util.ArrayList;
import java.util.List;

public class LotteryActivity extends AppCompatActivity {
    private LotteryView nl;
    private TextView tvIntegral;

    private String[] arrDescs = {"20元现金优\n惠券", "价值588元\n京佳口腔洗牙卡", "100元现金\n优惠券", "途牛旅游1663元\n组合出行优惠券", "", "星美影院9元\n通用立减券", "50元现金优\n惠券",
            "幸福西饼30元\n优惠券", "免服务费权益"};

    int[] arrImgs = {R.drawable.icon_lottery_prize_1, R.drawable.icon_lottery_prize_2, R.drawable.icon_lottery_prize_3, R.drawable
            .icon_lottery_prize_4, R.drawable.icon_lottery_start, R.drawable.icon_lottery_prize_6, R.drawable.icon_lottery_prize_7, R.drawable
            .icon_lottery_prize_8, R.drawable.icon_lottery_prize_9};

    private int integral = 50;
    private int count = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_lottery);

        nl = (LotteryView) findViewById(R.id.nl);
        tvIntegral = (TextView) findViewById(R.id.tv_integral);
        tvIntegral.setText("您当前拥有"+integral+"积分,10积分抽取一次");

        int[] prizesIcon = {R.drawable.navicon_a, R.drawable.navicon_b, R.drawable.navicon_c, R.drawable.navicon_d,
                R.drawable.icon_lottery_start, R.drawable.navicon_f, R.drawable.navicon_g, R.drawable.navicon_h, R.drawable.navicon_i};
        final List<Prize> prizes = new ArrayList<Prize>();
        for (int x = 0; x < 9; x++) {
            Prize lottery = new Prize();
            lottery.setId(x + 1);
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), arrImgs[x]);
            lottery.setIcon(bitmap);
            lottery.setDesc(arrDescs[x]);
            lottery.setDescColor(0xFF266353);

            prizes.add(lottery);
        }
        nl.setBmBg(BitmapFactory.decodeResource(getResources(), R.drawable.icon_lottery_bg));
        nl.setBgColor(0xFFCAF3E5);
        nl.setBmChoose(BitmapFactory.decodeResource(getResources(), R.drawable.icon_lottery_choose));
        nl.setBmPrizeBg(BitmapFactory.decodeResource(getResources(), R.drawable.icon_lottery_prize_bg));
        nl.setPrizes(prizes);
        nl.setOnTransferWinningListener(new LotteryView.OnTransferWinningListener() {

            @Override
            public void onClickStart() {
                //请求接口判断能否开始抽奖
                if (integral >= 10) {
                    count++;
                    int awardNumber = 0;
                    switch (count){
                        case 1:
                            awardNumber = 1;
                            break;
                        case 2:
                            awardNumber = 3;
                            break;
                        case 3:
                            awardNumber = 5;
                            break;
                        case 4:
                            awardNumber = 7;
                            break;
                    }
                    nl.setLottery(awardNumber);
                    nl.start();
                }else {
                    Toast.makeText(LotteryActivity.this,"当前积分不足",Toast.LENGTH_SHORT).show();
                    nl.setStartFlags(false);
                }
            }

            @Override
            public void onWinning(int position) {
                integral -= 10;
                tvIntegral.setText("您当前拥有"+integral+"积分,10积分抽取一次");
                Toast.makeText(getApplicationContext(), "恭喜获得:"+prizes.get(position).getDesc(), Toast.LENGTH_SHORT).show();
            }
        });
    }
}
2016-06-23 11:44:26 han63504 阅读数 8364

我们在开发中多多少少会遇到九宫格要求布局UI   如下图


 直接上代码


    //每个Item宽高
    CGFloat W = 80;
    CGFloat H = 100;
    //每行列数
    NSInteger rank = 4;
    //每列间距
    CGFloat rankMargin = (self.view.frame.size.width - rank * W) / (rank - 1);
    //每行间距
    CGFloat rowMargin = 20;
    //Item索引 ->根据需求改变索引
    NSUInteger index = 9;
    
    for (int i = 0 ; i< index; i++) {
        //Item X轴
        CGFloat X = (i % rank) * (W + rankMargin);
        //Item Y轴
        NSUInteger Y = (i / rank) * (H +rowMargin);
        //Item top
        CGFloat top = 50;
        UIView *speedView = [[UIView alloc] init];
        speedView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"taozi"]];
        speedView.frame = CGRectMake(X, Y+top, W, H);
        [self.view addSubview:speedView];
    }

只需要按照需求更改一下即可 



2015-08-28 10:35:04 qiuxuewei2012 阅读数 3057

搭建九宫格的步骤:

明确每一块用的是什么view

明确每个view之间的父子关系

先尝试逐个逐个添加格子,最后考虑使用for循环

加载app数据,根据数据长度创建对应个数的格子

添加格子内部的子控件

给格子内部的子控件装配数据

效果图:
这里写图片描述

代码:

- (void)viewDidLoad
{
    [super viewDidLoad];
    //搭建界面-九宫格!!
#define kAppViewH 80 //每个小视图高80
#define kAppViewW 80 //每个小视图宽80
#define kColCount 3 //每行视图数量一定,都是三个
#define kStart 20   //适配屏幕,起点20
    CGFloat marginX = (self.view.bounds.size.width - kColCount * kAppViewW) / (kColCount + 1);//每一列的x值一定
    CGFloat marginY = 10;//每一行的Y值一定由行号决定
    for (int i=0; i<12; i++) {
        //行号
        int row = i/kColCount;

        //列号
        int col = i%kColCount;

        //x - 由列号决定
        CGFloat x = marginX + col * (kAppViewW + marginX);

        //y - 由行号决定
        CGFloat y = kStart + marginY + row * (kAppViewH + marginY);

        //CGFloat
        UIView *appView = [[UIView alloc]initWithFrame:CGRectMake(x, y, kAppViewW, kAppViewH)];
        appView.backgroundColor = [UIColor redColor];
        [self.view addSubview:appView];
    }

}

运行结果:
这里写图片描述

2016-08-12 19:33:41 POPLAR_B 阅读数 1326


    //子控件高
    CGFloat w = 74;
    //子控件宽
    CGFloat h = w;
    //列数
    int colCount = 3;
    //计算间距
    CGFloat margin = (self.frame.size.width - 3 * w) / 4;

	//self.subviews.count 装view的组的个数
    for (int i = 0; i < self.subviews.count; i++) {
	    //self.subviews[i]装view的组数
        UIButton* btn = self.subviews[i];
        CGFloat x = (i % colCount) * (margin + w) + margin;
        CGFloat y = (i / colCount) * (margin + w) + margin;
        [btn setFrame:CGRectMake(x, y, w, h)];
    }



IOS-九宫格坐标计算

阅读数 3984