IOS_UI_控件总结+九宫格+仿QQ好友列表+小图片拉伸

H:/0718/00_UIKit_控件总结.m
一、UIView常见属性
1.frame  位置和尺寸(以父控件的左上角为原点(0,0))
2.center 中点(以父控件的左上角为原点(0,0))
3.bounds  位置和尺寸(以自己的左上角为原点(0,0))
4.transform  形变属性(缩放、旋转)
5.backgroundColor 背景颜色
6.tag  标识(父控件可以根据这个标识找到对应的子控件,同一个父控件中的子控件tag不要一样)
7.hidden 设置是否要隐藏
8.alpha  透明度(0~1)
9.opaque 不透明度(0~1)
10.userInteractionEnabled  能否跟用户进行交互(YES能交互)
11.superview 父控件
12.subviews 子控件
13.contentMode 内容显示的模式
二、UIView常见方法
1.addSubview:
添加子控件,被添加到最上面(subviews中的最后面)
2.removeFromSuperview
从父控件中移除
3.viewWithTag:
父控件可以根据这个tag标识找到对应的子控件(遍历所有的子控件)
4.insertSubview:atIndex:
添加子控件到指定的位置
5.利用两个类方法执行动画
+ (void)beginAnimations:(NSString *)animationID context:(void *)context;
/* ...需要执行动画的代码..*/
+ (void)commitAnimations;
6.利用block执行动画
/* duration 动画持续时间
 animations 存放需要执行动画的代码
 completion  存放动画完毕后需要执行的操作代码*/
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion
三、UIControl
1.只要继承了UIControl,就能简单处理一些事件(点击事件、值改变事件)
2.继承了UIControl的子类:
UIButton、UISlider、UISwitch、UIDatePicker等等
3.当需要监听一个子控件事件的时候,解决步骤:
1> 先看它是否继承自UIControl
2> 再看它内部是否有delegate属性
4.常用属性
1> enabled 能否处理事件,跟UIView的userInteractionEnabled属性类似
2> contentVerticalAlignment 内容在垂直方向上的排布方式
3> contentHorizontalAlignment 内容在水平方向上的排布方式
5.常用方法
1> 添加监听器
/* target 监听器对象
 action  事件触发时所调用的方法,调用target的方法
 controlEvents 事件类型 */
- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;
2> 删除监听器
// 删除监听器后,事件触发时就不会再通知监听器了,也就不会再调用target的action方法了
- (void)removeTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;
3> 获得所有的监听器对象
- (NSSet *)allTargets;
四、UILabel的常见属性
1.text 所显示的文本内容
2.textColor  文本颜色
3.font  字体
4.shadowColor 文字的阴影颜色
5.shadowOffset 阴影的偏差距离(width水平方向的偏差距离,正数右边、height垂直方向的偏差距离,正数下边)
6.textAlignment  设置文字的排布方式(偏左、偏右、居中)
7.numberOfLines 允许文字最多有几行(默认是1,如果为0,自动换行)
五、UIButton
1.常见属性
1> titleLabel 获取内部的UILabel对象
2> imageView 获取内部的UIImageView对象
2.常见方法
1> 设置内部UILabel显示的文本内容
// 设置按钮文本的时候不能  btn.titleLabel.text = @"4324324";
- (void)setTitle:(NSString *)title forState:(UIControlState)state;
2> 设置内部UILabel的文字颜色
- (void)setTitleColor:(UIColor *)color forState:(UIControlState)state;
3> 设置内部UILabel的文字阴影颜色
- (void)setTitleShadowColor:(UIColor *)color forState:(UIControlState)state;
4> 设置内部UIImageView的图片
// 设置内部UIImageView的图片不能:btn.imageView.image = [UIImage imagedName:@"0.png"];
- (void)setImage:(UIImage *)image forState:(UIControlState)state;
5> 设置背景图片
- (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state;
6> 下面两个方法需要交给子类去重写
// 返回内部UILabel的frame(位置和尺寸)
- (CGRect)titleRectForContentRect:(CGRect)contentRect;
// 返回内部UIImageView的frame(位置和尺寸)
- (CGRect)imageRectForContentRect:(CGRect)contentRect;
7> 下面这些方法可以获取不同状态下的一些属性值
- (NSString *)titleForState:(UIControlState)state;     
- (UIColor *)titleColorForState:(UIControlState)state;
- (UIColor *)titleShadowColorForState:(UIControlState)state;
- (UIImage *)imageForState:(UIControlState)state;
- (UIImage *)backgroundImageForState:(UIControlState)state;

H:/0718/01_九宫格_MJViewController.h
//  MJViewController.h
//  01-九宫格
//  Created by apple on 13-7-18.
//  Copyright (c) 2013年 itcast. All rights reserved.
/* 1.添加图片资源
 2.初始化测试数据(Product)
 3.添加UITableView(数据源、代理、实现相应的方法) 
 4.自定义Cell(ProductRowCell,创建3、4、5个格子) 
 5.设置显示的数据(截取每一行Cell所需的数据,再按顺序显示到对应的格子上)
 6.调整按钮内部UIImageView和UILabel的位置*/
 
#import <UIKit/UIKit.h>
@interface MJViewController : UITableViewController
@end

H:/0718/01_九宫格_MJViewController.m
//  MJViewController.m
//  01-九宫格
//  Created by apple on 13-7-18.
//  Copyright (c) 2013年 . All rights reserved.
/* 1.添加图片资源
 2.初始化测试数据(Product)
 3.添加UITableView(数据源、代理、实现相应的方法) 
 4.自定义Cell(ProductRowCell,里面可以随便创建3、4、5个格子) 
 5.重点!!!设置显示的数据(截取每一行Cell所需的数据组成参数数组,再交给cell按顺序显示到对应的格子上)
 6.自定义按钮,目的是重写方法,方便调整按钮内部UIImageView和UILabel的位置*/
#import "MJViewController.h"
#import "Product.h"
#import "ProductRowCell.h"
@interface MJViewController ()
//成员可变数组,模拟数据来源,填充假数据
@property (nonatomic, strong) NSMutableArray *products;
@end
@implementation MJViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
    // 不允许选中TableView的一整行
    self.tableView.allowsSelection = NO;
    // 初始化产品数据
    self.products = [NSMutableArray array];
    for (int i = 1; i<=39; i++) {
        // 初始化产品对象
        Product *p = [[Product alloc] init];
        // 设置产品名称
        p.name = [NSString stringWithFormat:@"产品-%d", i];
        // 设置产品图标(1~11.png)
        int iconIndex = arc4random_uniform(11) + 1;
        p.icon = [NSString stringWithFormat:@"images.bundle/tmall_icon_cat_outing_%d.png", iconIndex];
        // 添加产品到成员产品数组
        [self.products addObject:p];
    }
}
#pragma mark - 数据源、代理方法
#pragma mark numberOfRowsInSection,返回对应Section的行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    /*
     假设列数为3,即每一row显示三个按钮(每个按钮展示一个产品)
     1.情况之一:产品个数除于列数的余数为0
     个数:3、6、9、12、15。。。。
     行数:1、2、3、 4、5。。。。个数/列数
     
     2.情况之二:产品个数除于列数的余数不为0  
     个数:4、7、16。。。。
     行数:2、3、6。。。。个数/列数 + 1*/
     
    /*
    if (self.products.count%kColumn==0) { // 余数为0
        return self.products.count/kColumn;
    } else { // 余数不为0
        return self.products.count/kColumn + 1;
    }*/
    // 优化的算法,行数 = (产品数 + 列数 -1)/列数
    return (self.products.count + kColumn - 1) / kColumn;
}

#pragma mark 每当有一个cell进入视野范围内就会调用,返回当前这行显示的cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 0.用static修饰的局部变量,只会初始化一次
    static NSString *ID = @"cell";
    // 1.拿到一个标识先去缓存池中查找对应的Cell(ProductRowCell)
    ProductRowCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    // 2.如果缓存池中没有,才需要传入一个标识创建新的Cell
    if (cell == nil) {
        cell = [[ProductRowCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
    }
	// 3.为cell填充独一无二的数据!
	// 自定义Cell:每一个Cell里面都有N个格子,N即常量列数kColumn
	//截取这行Cell所需的产品数据
     /*假设产品总个数:16
	 每行显示3个格子,即MyButton(内含产品图片和名称)
     则产品索引范围:0~15
    cell的行号  对应所需展现的产品的索引值范围(注意最后一个cell)
        0:      0 1 2
        1:      3 4 5
        2:      6 7 8
        3:      9 10 11
        4:      12 13 14
        5:      15*/
    // 从产品数组中,截取的开始位置,即所在行号 * 常量列数
    int location = indexPath.row * kColumn;
    // 从产品数组,要截取的长度(即要分配给对应row的cell的产品)
    int length = kColumn;
    // 特殊情况:最后一行的cell,可能产品不够,如果截取的范围越界
    if (location + length >= self.products.count) {
		//给最后一行的cell,分派产品,供它展示
		//例如:16-15=1,最后一行的cell只能展示一个格子
        length = self.products.count - location;
    }
    // 从产品数组,要给对应的row的cell,分派的产品个数,即截取范围
    NSRange range = NSMakeRange(location, length);
    // 根据截取范围,从产品总数组中,获取这行所需的产品个数,交给cell自行填充
    NSArray *rowProducts = [self.products subarrayWithRange:range];    
    // cell自行填充,设置这个行Cell所需的产品数据
    [cell setRowProducts:rowProducts];
    return cell;
}
#pragma mark 每一行的高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return kCellHeight;
}

@end

H:/0718/01_九宫格_MyButton.h
//  MyButton.h
//  01-九宫格
//  Created by apple on 13-7-18.
//  Copyright (c) 2013年 itcast. All rights reserved.
#import <UIKit/UIKit.h>
@interface MyButton : UIButton
@end

H:/0718/01_九宫格_MyButton.m
//  MyButton.m
//  01-九宫格
//  Created by apple on 13-7-18.
//  Copyright (c) 2013年 itcast. All rights reserved.

//自定义按钮 继承自UIButton

// 按钮里面,图片所占的高度比例
#define kImageRatio 0.7
#import "MyButton.h"
@implementation MyButton
#pragma mark 任何方式(代码)创建按钮都会调用这个方法
- (id)initWithFrame:(CGRect)frame
{
	//先调用父类的方法
    if (self = [super initWithFrame:frame]) {
        // 设置按钮文字颜色
        [self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];        
        // 设置按钮中的文字居中
        self.titleLabel.textAlignment = NSTextAlignmentCenter;
        // 让图片按照原来的宽高比显示出来,即自适应AspectFit
        self.imageView.contentMode = UIViewContentModeScaleAspectFit;
        // 设置按钮文字的字体尺寸
        self.titleLabel.font = [UIFont systemFontOfSize:15];
        // 设置按钮里面的内容(即控件UILabel、UIImageView)居中
        // btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
    }
    return self;
}

#pragma mark - 重写UIButton的imageRectForContentRect方法
#pragma mark 目的是要控制按钮里面的UIImageView的位置和尺寸
//  参数:contentRect其实就是按钮的位置和尺寸
//  返回值:按钮里面的UIImageView的位置和尺寸
- (CGRect)imageRectForContentRect:(CGRect)contentRect
{
    CGFloat imageX = 0;
    CGFloat imageY = 0;
	//按钮里面的图片宽:为按钮宽
    CGFloat imageWidth = contentRect.size.width;
	//按钮里面的图片高:为按钮高*0.7
    CGFloat imageHeight = contentRect.size.height * kImageRatio;
    return CGRectMake(imageX, imageY, imageWidth, imageHeight);
}

#pragma mark - 重写UIButton的titleRectForContentRect方法
#pragma mark 目的是要控制按钮里面的UILabel的位置和尺寸
//  参数:contentRect其实就是按钮的位置和尺寸
//  返回值:按钮里面的UILabel的位置和尺寸
- (CGRect)titleRectForContentRect:(CGRect)contentRect
{
    CGFloat titleX = 0;
	//按钮里面UILabel的Y:为图片的最大Y值(即最下面的位置)
    CGFloat titleY = contentRect.size.height * kImageRatio;
	//按钮里面的UILabel宽:为按钮宽
    CGFloat titleWidth = contentRect.size.width;
	//按钮里面的UILabel高:为按钮高-Y坐标(即按钮内除去图片余下的所有高度)
    CGFloat titleHeight = contentRect.size.height - titleY;
    return CGRectMake(titleX, titleY, titleWidth, titleHeight);
}
@end

H:/0718/01_九宫格_Product.h
//  Product.h
//  01-九宫格
//  Created by apple on 13-7-18.
//  Copyright (c) 2013年 itcast. All rights reserved.
//  产品类
#import <Foundation/Foundation.h>
@interface Product : NSObject
// 产品图片名
@property (nonatomic, strong) NSString *icon;
// 产品名称
@property (nonatomic, strong) NSString *name;
@end

H:/0718/01_九宫格_Product.m
//  Product.m
//  01-九宫格
//  Created by apple on 13-7-18.
//  Copyright (c) 2013年 itcast. All rights reserved.
#import "Product.h"
@implementation Product
@end

H:/0718/01_九宫格_ProductRowCell.h
//  ProductRowCell.h
//  01-九宫格
//  Created by apple on 13-7-18.
//  Copyright (c) 2013年 itcast. All rights reserved.
#import <UIKit/UIKit.h>
// 每一行要显示多少列数
#define kColumn 5
// 每一行cell的高度
#define kCellHeight 100
@interface ProductRowCell : UITableViewCell
// 设置这一行对应的产品数据(1~3),例如排3列时,前面参数是3个产品,最后一行可能只有1-2个产品
- (void)setRowProducts:(NSArray *)rowProducts;
@end

H:/0718/01_九宫格_ProductRowCell.m
//  ProductRowCell.m
//  01-九宫格
//  Created by apple on 13-7-18.
//  Copyright (c) 2013年 itcast. All rights reserved.
//定义每个格子,即按钮的tag起始值,方便找到cell中对应的MyButton
#define kTagStart 100
#import "ProductRowCell.h"
#import "Product.h"
#import "MyButton.h"
@implementation ProductRowCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
	//先调用父类的构造方法
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // 根据常量:每一行cell要显示的列数添加对应数目个格子
        // self.frame.size.height 永远是44
        for (int i = 0; i<kColumn; i++) {
            // 初始化格子(自定义的button,只能用custome样式)按钮的构造方法内设置了...
            MyButton *btn = [MyButton buttonWithType:UIButtonTypeCustom];
            //[[MyButton alloc] initWithFrame:<#(CGRect)#>];
            //[[MyButton alloc] init];
            // 设置一行中,每个格子的宽高和位置
			//每个格子的宽:cell一行的宽/列数(即一行的格子数)
            CGFloat btnWidth = self.frame.size.width / kColumn;
			//每个格子的x坐标:i*格子宽
            CGFloat btnX = i * btnWidth;
			//每个格子的y都是0
            CGFloat btnY = 0;
			//每个格子的高度,就是cell的高度
            CGFloat btnHeight = kCellHeight;
            btn.frame = CGRectMake(btnX, btnY, btnWidth, btnHeight);
            // 设置每个格子的tag,方便填充产品数据到cell中的每个格子
            btn.tag = i + kTagStart;
            // 添加格子到cell的contentView中
            [self.contentView addSubview:btn];
        }
    }
    return self;
}
#pragma mark 设置所有格子的数据(个数可能是1、2、3、...kColumn)
// 参数:对应个数的产品组成的数组(可能是3个,最后一行row对应的cell也可能是2个,或1个)
- (void)setRowProducts:(NSArray *)rowProducts
{
    // 遍历所有的格子
    for (int i = 0; i<kColumn; i++) {
        // 格子的tag
        int tag = i + kTagStart;
        // 取出对应的格子
        MyButton *btn = (MyButton *)[self.contentView viewWithTag:tag];
        // 重点!!!!!如果这个格子没有对应的数据,特别是指最后一行cell的格子
		//条件:如果i > 参数数组里最大的下标
        if (i>rowProducts.count - 1) {
            btn.hidden = YES; // 由于没有产品数据要展现,隐藏格子
        } else { // 如果这个格子有对应的数据
            // 获得这个格子对应的产品数据
            Product *p = rowProducts[i];
            // 设置格子的产品名称
            [btn setTitle:p.name forState:UIControlStateNormal];
            // 设置格子显示的图片
            UIImage *image = [UIImage imageNamed:p.icon];
            // 设置内部UIImageView的图片
            [btn setImage:image forState:UIControlStateNormal];
            // 设置背景图片,会被拉伸
            //[btn setBackgroundImage:image forState:UIControlStateNormal];
            //记住!千万要显示格式(产品),在cell重用reuse时见效果~~~
            btn.hidden = NO; // 显示格子
        }
    }
}
@end

H:/0718/02_QQ好友列表_friends.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
	<dict>
		<key>group</key>
		<string>我的好友</string>
		<key>friends</key>
		<array>
			<string>2B</string>
			<string>战斗机</string>
			<string>西门吹雪</string>
			<string>西门抽血</string>
			<string>西门抽筋</string>
			<string>西门抽奖</string>
			<string>西门庆</string>
		</array>
	</dict>
	<dict>
		<key>group</key>
		<string>大学同学</string>
		<key>friends</key>
		<array>
			<string>大学同学1</string>
			<string>大学同学2</string>
			<string>大学同学3</string>
			<string>大学同学4</string>
			<string>大学同学5</string>
			<string>大学同学6</string>
			<string>大学同学7</string>
			<string>大学同学8</string>
		</array>
	</dict>
	<dict>
		<key>group</key>
		<string>高中同学</string>
		<key>friends</key>
		<array>
			<string>高中同学1</string>
			<string>高中同学2</string>
			<string>高中同学3</string>
		</array>
	</dict>
	<dict>
		<key>group</key>
		<string>初中同学</string>
		<key>friends</key>
		<array>
			<string>初中同学1</string>
			<string>初中同学2</string>
			<string>初中同学3</string>
			<string>初中同学4</string>
			<string>初中同学5</string>
			<string>初中同学6</string>
		</array>
	</dict>
	<dict>
		<key>group</key>
		<string>小学同学</string>
		<key>friends</key>
		<array>
			<string>小学同学1</string>
			<string>小学同学2</string>
			<string>小学同学3</string>
			<string>小学同学4</string>
			<string>小学同学5</string>
		</array>
	</dict>
	<dict>
		<key>group</key>
		<string>老乡</string>
		<key>friends</key>
		<array>
			<string>老乡1</string>
			<string>老乡2</string>
			<string>老乡3</string>
			<string>老乡4</string>
		</array>
	</dict>
	<dict>
		<key>group</key>
		<string>欠我钱的</string>
		<key>friends</key>
		<array>
			<string>王八羔子</string>
			<string>

H:/0718/02_QQ好友列表_HeaderView.h
//  HeaderView.h
//  02-QQ好友列表
//  Created by apple on 13-7-18.
//  Copyright (c) 2013年 itcast. All rights reserved.
#import <UIKit/UIKit.h>
//实际上是一个按钮
@interface HeaderView : UIButton
@end

H:/0718/02_QQ好友列表_HeaderView.m
//  HeaderView.m
//  02-QQ好友列表
//  Created by apple on 13-7-18.
//  Copyright (c) 2013年 itcast. All rights reserved.
#import "HeaderView.h"
@implementation HeaderView
//自定义按钮的构造方法
- (id)initWithFrame:(CGRect)frame
{
	//先调用父类的构造方法
    self = [super initWithFrame:frame];
    if (self) {
		//图片显示模式:自适应
        //self.imageView.contentMode = UIViewContentModeScaleAspectFit;
        // 只允许这种方法设置按钮内部UIImageview要显示的图片
        [self setImage:[UIImage imageNamed:@"disclosure.png"] forState:UIControlStateNormal];
        //[self setBackgroundImage:<#(UIImage *)#> forState:<#(UIControlState)#>];
    }
    return self;
}
#pragma mark 重写按钮的方法,目的是设置UIImageView的位置和尺寸
- (CGRect)imageRectForContentRect:(CGRect)contentRect
{
    return CGRectMake(0, 0, 32, 32);
}
@end

H:/0718/02_QQ好友列表_MJViewController.h
//  MJViewController.h
//  02-QQ好友列表
//  Created by apple on 13-7-18.
//  Copyright (c) 2013年 itcast. All rights reserved.
/* 1.加载好友数据
 2.简单地分组显示好友数据
 3.实现tableView:viewForHeaderInSection:方法返回每一组的标题对象
 4.监听标题的点击事件
   * 初始化一个字典对象,用来记录每一组的状态(展开\合并)
   * 点击标题后,对每一组的状态进行取反
   * 刷新数据(reloadData)
 5.添加箭头*/
#import <UIKit/UIKit.h>
@interface MJViewController : UITableViewController
@end

H:/0718/02_QQ好友列表_MJViewController.m
//  MJViewController.m
//  02-QQ好友列表
//  Created by apple on 13-7-18.
//  Copyright (c) 2013年 itcast. All rights reserved.
/* 1.加载好友数据,mainBundle得到path,根据path得到字典数组,
字典数组的:每个成员都是字典,字典中共2对键值,
其中"group"对应分组名,"friends"对应数组,
数组每个成员都是一个好友名称
 2.简单地分组显示好友数据
 3.实现tableView:viewForHeaderInSection:方法返回每一组的标题对象视图
 4.监听标题的点击事件
   * 初始化一个字典对象,作用是:记录每一组的状态(展开\合并)
   * 点击标题后,对每一组的状态进行取反
   * 刷新数据(reloadData)
 5.添加箭头*/
#import "MJViewController.h"
#import "HeaderView.h"
@interface MJViewController ()
/*字典数组的:每个成员都是字典,字典中共2对键值,
其中"group"对应分组名,"friends"对应数组,
数组每个成员都是一个好友名称*/
@property (nonatomic, strong) NSArray *allFriends;
// 存放所有组的展开\合并状态
// key=组号  value=对应组的状态(1代表展开,0代表合并)
@property (nonatomic, strong) NSMutableDictionary *status;
@end
@implementation MJViewController
#pragma mark - View加载完毕
- (void)viewDidLoad
{
    [super viewDidLoad];
    // 加载好友数据
    NSString *path = [[NSBundle mainBundle] pathForResource:@"friends" ofType:@"plist"];
    self.allFriends = [NSArray arrayWithContentsOfFile:path];
    // 初始化状态字典
    self.status = [NSMutableDictionary dictionary];
}
#pragma mark - 数据源、代理方法
#pragma mark 有多少组数据
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
	//字典数组中字典的个数,即分组数
    return self.allFriends.count;
}
#pragma mark 每一组中有多少行数据
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // 取出第section组对应的状态
    int result = [self.status[@(section)] intValue];
    if (result == 0) { 
		// 代表当前组是:合并状态,故返回0行,即不显示
        return 0;
    } else { // 展开状态
        // 1.先获取这组对应的数据
        NSDictionary *group = self.allFriends[section];
        // 2.获取这组里面的好友数组,返回好友数组长度
        NSArray *friends = group[@"friends"];
        return friends.count;
    }
}
#pragma mark 每当有一个cell进入视野范围内就会调用,返回当前这行显示的cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 0.用static修饰的局部变量,只会初始化一次
    static NSString *ID = @"cell";
    // 1.拿到一个标识先去缓存池中查找对应的Cell
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    // 2.如果缓存池中没有,才需要传入一个标识创建新的Cell
    if (cell == nil) {
		//UITableViewCellStyleSubtitle
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
    }
    // 3.封装这行独一无二的数据
    // 3.1 获取这组对应的字典数据
    NSDictionary *dict = self.allFriends[indexPath.section];
    // 3.2 获取这组的好友数据
    NSArray *friends = dict[@"friends"];
	// 3.3 设置具体数据,好友名称
    cell.textLabel.text = friends[indexPath.row];    
    cell.imageView.image = [UIImage imageNamed:@"me.jpeg"];
    cell.detailTextLabel.text = @"正在输入中....";
    return cell;
}
#pragma mark 每一行的高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 50;
}
#pragma mark 每一组标题的高度
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 40;
}
#pragma mark 第section组对应的标题
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{	
	//创建自定义按钮HeaderView,作为标题栏,目的响应点击,进行展开和闭合
    HeaderView *titleView = [HeaderView buttonWithType:UIButtonTypeCustom];
    // 设置标题内容
    NSDictionary *dict = self.allFriends[section];
    [titleView setTitle:dict[@"group"] forState:UIControlStateNormal];
    // 设置标题颜色
    [titleView setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    // 设置背景颜色
    [titleView setBackgroundColor:[UIColor grayColor]];
    // 重点!!!设置按钮的tag为组号,方便点击方法里面调用!
    titleView.tag = section;
    // 监听标题点击
    [titleView addTarget:self action:@selector(titleClick:) forControlEvents:UIControlEventTouchUpInside];
    // 取出第section组的状态
    int result = [self.status[@(section)] intValue];
    // 对状态进行取反
    if (result == 0) {
		//如果是闭合,图片箭头向右
        titleView.imageView.transform = CGAffineTransformIdentity;
    } else {
		//如果是展开,图片箭头向下,顺时针转90度
        titleView.imageView.transform = CGAffineTransformMakeRotation(M_PI_2);
    }
    return titleView;
}
#pragma mark - 监听标题点击,先改数据模型,再刷新视图
- (void)titleClick:(UIButton *)btn {
    // 取出标题按钮对应的组号,即为被单击的组
    int section = btn.tag;
    // 取出第section组的状态
    int result = [self.status[@(section)] intValue];
    // 对状态进行取反
    if (result == 0) {
        [self.status setObject:@1 forKey:@(section)];
    } else {
        [self.status setObject:@0 forKey:@(section)];
    }
    // 刷新数据(会重新给数据源发送消息)
    [self.tableView reloadData];
}
//下面这个代理方法,只能设置标题的文字,不能设置标题的视图view
//- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
//{
//    // 1.获取这组对应的字典数据
//    NSDictionary *dict = self.allFriends[section];
//    return dict[@"group"];
//}
@end

H:/0718/03_小图片拉伸_MJViewController.m
//  MJViewController.m
//  03-小图片拉伸
//  Created by apple on 13-7-18.
//  Copyright (c) 2013年 itcast. All rights reserved.
#import "MJViewController.h"
@interface MJViewController ()
@end
@implementation MJViewController
- (void)viewDidLoad
{
    [super viewDidLoad];   
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
    btn.frame = CGRectMake(10, 10, 250, 200);
    [btn setTitle:@"rsdrwerwerwerwer" forState:UIControlStateNormal];
    UIImage *image = [UIImage imageNamed:@"chatfrom_bg_normal.png"];
    // 设置图片左边不需要拉伸的宽度
    CGFloat leftWidth = image.size.width * 0.5;
    // 设置图片顶部不需要拉伸的高度
    CGFloat topHeight = image.size.height * 0.6;
	//IOS4.0已经存在的方法stretchableImageWithLeftCapWidth
    image = [image stretchableImageWithLeftCapWidth:leftWidth topCapHeight:topHeight];
    [btn setBackgroundImage:image forState:UIControlStateNormal];
    [self.view addSubview:btn];
    /*
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
    btn.frame = CGRectMake(100, 100, 100, 60);
	UIImage *image = [UIImage imageNamed:@"bg.png"];
    image = [image stretchableImageWithLeftCapWidth:image.size.width * 0.5 topCapHeight:image.size.height * 0.5];
    [btn setBackgroundImage:image forState:UIControlStateNormal];
    [self.view addSubview:btn];*/    
    //UIEdgeInsetsMake(<#CGFloat top#>, <#CGFloat left#>, <#CGFloat bottom#>, <#CGFloat right#>)
    // ios 5.0 UIEdgeInsets可以分别设置上下左右不需要拉伸的范围
    [image resizableImageWithCapInsets:<#(UIEdgeInsets)#>];
    // ios 6.0UIImageResizingMode可以设置是Tile平铺,还是stretch拉撑
    [image resizableImageWithCapInsets:<#(UIEdgeInsets)#> resizingMode:<#(UIImageResizingMode)#>];
}
@end

H:/0718/04_QQ好友列表_friends.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
	<dict>
		<key>group</key>
		<string>我的好友</string>
		<key>friends</key>
		<array>
			<string>2B</string>
			<string>战斗机</string>
			<string>西门吹雪</string>
			<string>西门抽血</string>
			<string>西门抽筋</string>
			<string>西门抽奖</string>
			<string>西门庆</string>
		</array>
	</dict>
	<dict>
		<key>group</key>
		<string>大学同学</string>
		<key>friends</key>
		<array>
			<string>大学同学1</string>
			<string>大学同学2</string>
			<string>大学同学3</string>
			<string>大学同学4</string>
			<string>大学同学5</string>
			<string>大学同学6</string>
			<string>大学同学7</string>
			<string>大学同学8</string>
		</array>
	</dict>
	<dict>
		<key>group</key>
		<string>高中同学</string>
		<key>friends</key>
		<array>
			<string>高中同学1</string>
			<string>高中同学2</string>
			<string>高中同学3</string>
		</array>
	</dict>
	<dict>
		<key>group</key>
		<string>初中同学</string>
		<key>friends</key>
		<array>
			<string>初中同学1</string>
			<string>初中同学2</string>
			<string>初中同学3</string>
			<string>初中同学4</string>
			<string>初中同学5</string>
			<string>初中同学6</string>
		</array>
	</dict>
	<dict>
		<key>group</key>
		<string>小学同学</string>
		<key>friends</key>
		<array>
			<string>小学同学1</string>
			<string>小学同学2</string>
			<string>小学同学3</string>
			<string>小学同学4</string>
			<string>小学同学5</string>
		</array>
	</dict>
	<dict>
		<key>group</key>
		<string>老乡</string>
		<key>friends</key>
		<array>
			<string>老乡1</string>
			<string>老乡2</string>
			<string>老乡3</string>
			<string>老乡4</string>
		</array>
	</dict>
	<dict>
		<key>group</key>
		<string>欠我钱的</string>
		<key>friends</key>
		<array>
			<string>王八羔子</string>
			<string>

H:/0718/04_QQ好友列表_Header.h
//
//  Header.h
//  QQ好友列表
//
//  Created by mj on 13-7-18.
//  Copyright (c) 2013年 itcast. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface Header : UIButton
//按钮成员,记住是否展开该组
@property (nonatomic, assign) BOOL open;
@end

H:/0718/04_QQ好友列表_Header.m
//  Header.m
//  QQ好友列表
//  Created by mj on 13-7-18.
//  Copyright (c) 2013年 itcast. All rights reserved.
#import "Header.h"
@implementation Header
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self setImage:[UIImage imageNamed:@"disclosure.png"] forState:UIControlStateNormal];
        self.imageView.contentMode = UIViewContentModeScaleAspectFit;
        self.adjustsImageWhenHighlighted = NO;
    }
    return self;
}
- (void)setOpen:(BOOL)open
{
    _open = open;
    [UIView beginAnimations:nil context:nil];
	//如果展开该组,图片的箭头向下
	//如果关闭该组,图片的箭头向右
    self.imageView.transform = CGAffineTransformMakeRotation(_open?M_PI_2:0);
    [UIView commitAnimations];
}
//重写按钮的方法,返回ImageView的位置和尺寸
- (CGRect)imageRectForContentRect:(CGRect)contentRect
{
    return CGRectMake(0, 0, 25, contentRect.size.height);
}
//重写按钮的方法,返回Lable的位置和尺寸
- (CGRect)titleRectForContentRect:(CGRect)contentRect
{
    return CGRectMake(30, 0, contentRect.size.width, contentRect.size.height);
}
@end

H:/0718/04_QQ好友列表_MJViewController.m
//  MJViewController.m
//  QQ好友列表
//  Created by mj on 13-7-17.
//  Copyright (c) 2013年 itcast. All rights reserved.
#import "MJViewController.h"
#import "Header.h"
@interface MJViewController ()
//字典数组,每个成员是一个字典,字典中有两对k--v
//group-->组名
//friends-->好友名组成的数组
@property (nonatomic, strong) NSArray *friends;
//字典,记住,每一组的,标题view
@property (nonatomic, strong) NSMutableDictionary *headers;
@end
@implementation MJViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
	//全路径
    NSString *path = [[NSBundle mainBundle] pathForResource:@"friends" ofType:@"plist"];
	//字典数组
    self.friends = [NSArray arrayWithContentsOfFile:path];
	//初始化标题view组成的数组
    self.headers = [NSMutableDictionary dictionary];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
	//快速创建Number对象时,变量要加小括号
	//从成员数组中,取出对应section的标题view对象(实为自定义按钮)
    Header *header = self.headers[@(section)];
	//取出字典数组中的字典的好友数组的长度
    NSArray *groupFriends = self.friends[section][@"friends"];
	//如果是打开的,返回组内所有的行数,否则返回0行
    int count = header.open ? groupFriends.count : 0;
    return count;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
	//一共有多少组,只要返回字典数组的长度
    return self.friends.count;
}
#pragma mark 创建每一行的Cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
	//标准代码 1:
    static NSString *ID = @"cell";
	//标准代码 2:
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
	//标准代码 3:
    if(cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
    }
	//设置独一无二的数据,即好友名
    NSArray *groupFriends = self.friends[indexPath.section][@"friends"];
    cell.textLabel.text = groupFriends[indexPath.row];
    return cell;
}
//代理方法,设置每一组的标题要显示的view,为自定义view
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    Header *btn = self.headers[@(section)];
    if (!btn) {
		//如果为空,创建HeadView并添加到成员数组中
        btn = [Header buttonWithType:UIButtonTypeCustom];
        btn.backgroundColor = [UIColor orangeColor];
        btn.bounds = CGRectMake(0, 0, 320, 44);
		//字典数组中的字典中的组名
        NSString *group = self.friends[section][@"group"];
        [btn setTitle:group forState:UIControlStateNormal];
		//添加点击事件
        [btn addTarget:self action:@selector(expandGroup:event:) forControlEvents:UIControlEventTouchUpInside];
		//添加到成员数组中,其他方法中要用到
        [self.headers setObject:btn forKey:@(section)];
    }
    return btn;
}
//响应按钮点击,展开或关闭该组,然后刷新数据
- (void)expandGroup:(Header *)header event:(UIEvent *)event
{
    header.open = !header.open;
    [self.tableView reloadData];
}
@end

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 下面是一个示例代码,可以将N张图片转换为2*N张隔行扫描的小图片: ```python import cv2 import os def split_image(image, path, prefix): height, width, _ = image.shape for i in range(2): for j in range(N): small_image = image[i*height//2:(i+1)*height//2, j*width//N:(j+1)*width//N] filename = os.path.join(path, prefix + '_' + str(i*N+j) + '.jpg') cv2.imwrite(filename, small_image) N = 10 # 每张图片分割为 N*N 个小图片 src_path = './images' # 原始图片所在路径 dst_path = './split_images' # 分割后图片保存路径 prefix = 'image' # 图片文件名前缀 if not os.path.exists(dst_path): os.mkdir(dst_path) # 遍历原始图片目录 for file in os.listdir(src_path): if file.endswith('.jpg'): # 读取原始图片 image = cv2.imread(os.path.join(src_path, file)) # 分割为 2*N 个小图片 split_image(image, dst_path, prefix) ``` 这个程序将每张图片分割为 N*N 个小图片,并按照隔行扫描的方式排列,最终生成 2*N 张小图片,保存到指定的目录中。 ### 回答2: 要编写Python OpenCV程序将N幅图片批量转换为2*N幅隔行扫描的小图片,可以按照以下步骤操作: 1. 导入必要的库和模块,包括OpenCV和NumPy。 2. 设定原始图片的路径和扩展名,以及新生成图片的保存路径和扩展名。 3. 创建一个函数来实现图片转换功能。函数中可以包含以下步骤: - 使用OpenCV的imread函数加载原始图片。 - 获取图片的行数和列数。 - 创建一个新的空白图像,大小为原始图片行数的两倍,列数不变。 - 使用两个嵌套的循环,从原始图片中提取每个奇数行的像素,并将其复制到新生成图片的对应位置。 - 将新生成的图片保存到指定路径。 4. 使用一个循环,按照指定路径读取N幅原始图片,并调用函数进行转换操作。 下面是该程序的示例代码: ```python import cv2 import numpy as np # 原始图片路径和扩展名 original_path = "original/" original_ext = ".jpg" # 新生成图片保存路径和扩展名 new_path = "processed/" new_ext = ".jpg" # 转换函数 def convert_image(original_image_path, new_image_path): # 加载原始图片 original_image = cv2.imread(original_image_path) # 获取行数和列数 rows, cols, _ = original_image.shape # 创建新的空白图像 new_image = np.zeros((2*rows, cols, 3), np.uint8) # 逐行复制像素 for i in range(rows): if i % 2 == 0: new_image[2*i] = original_image[i] # 保存新生成的图片 cv2.imwrite(new_image_path, new_image) # 批量转换图片 N = 5 for i in range(1, N+1): original_image_path = original_path + str(i) + original_ext new_image_path = new_path + str(2*i) + new_ext convert_image(original_image_path, new_image_path) ``` 以上代码可以将N幅原始图片转换为2*N幅隔行扫描的小图片,并保存到指定路径。你可以根据自己的需求调整代码中的路径和参数。 ### 回答3: 编写Python OpenCV程序将N幅图片批量转换为2*N幅隔行扫描的小图片,您可以按照以下步骤进行: 1. 首先,导入所需的模块和库:OpenCV(cv2)、NumPy(numpy) 2. 创建一个函数来处理图片转换的逻辑。假设函数名为convert_images。 3. 在函数中,使用cv2.imread()函数逐个读取N幅图片。 4. 创建一个空的列表变量来存储转换后的小图片。 5. 使用循环迭代每个读取的图片。 6. 获取每个图片的长和宽。 7. 创建两个空白的画布,分别用于存储偶数行和奇数行的像素。 8. 使用两个嵌套的循环迭代每个像素。 9. 将偶数行像素存储到偶数行画布上,奇数行像素存储到奇数行画布上。 10. 将存储好的偶数行画布和奇数行画布按照目标格式(隔行扫描)合并为一张新的小图片。 11. 将合并好的小图片添加到之前创建的列表中。 12. 循环结束后,将存储所有小图片列表返回。 13. 在主程序中调用convert_images函数,传入N幅图片的路径作为参数。 14. 使用cv2.imwrite()函数逐个保存转换后的小图片。 15. 结束程序。 您可以根据实际需求和自身的编程风格对细节进行调整和完善。以上就是一个简单的实现思路来完成将N幅图片批量转换为2*N幅隔行扫描的小图片的Python OpenCV程序。希望能对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值