关于iOS自定义控件:在view上实现事件和代理
- 自定义控件.h
#import <UIKit/UIKit.h>
#import "PPViewtouchesBeginDelegate.h"
@interface PPView : UIView
// 这样写避免了内存泄露的问题
@property (nonatomic, strong)UIView *Pview;
// 保存鼠标点击在父视图上的位置和子视图的偏移量
@property (nonatomic, assign)CGPoint plusPoint;
// 接收传递过来的方法和对象:在touchesBegin时使用该对象调用该包装的方法
@property (nonatomic, strong)id sender;
@property (nonatomic, assign)SEL action;
// 代码加载完毕,通过方法实现保存了该对象和需要调用的SEL
- (void)addTarget:(id)target andAction:(SEL)action;
// 点击view显示字符串
@property (nonatomic, strong)NSString *PPText;
// 限定合适的代理(弱引用):触发是view被点击时
@property (nonatomic, weak)id<PPViewtouchesBeginDelegate> delegate;
@end
- 自定义控件代理
#import <Foundation/Foundation.h>
// 谁成为我的代理,谁就属于了我的类型:反向传值(代理应用_2)
@class PPView;
@protocol PPViewtouchesBeginDelegate <NSObject>
// - 确保传递出去的形参可以访问属性:谁触发就把谁传递出去
- (void)touchesPPVoewBegin:(PPView *)sender;
@end
- 自定义控件.m
#import "PPView.h"
@implementation PPView
// 1.在原view基础上添加了一个view:每次创建自定义view就会自带一个添加了的view
- (instancetype)initWithFrame:(CGRect)frame
{
// - 让该视图在被创建的父视图的中央
if (self = [super initWithFrame:frame])
{
// > 父类初始化成功后才给子类的frame赋值
CGFloat width = self.frame.size.width;
CGFloat height = self.frame.size.height;
// > 需要创建对象
_Pview = [[UIView alloc] initWithFrame:CGRectMake(width/4, height/4, width/2, height/2)];
_Pview.backgroundColor = [UIColor purpleColor];
// > 在传递过来的父视图上添加主视图,而不是在主视图上:self.view
[self addSubview:_Pview];
}
return self;
}
// 2.让添加的view能在父视图上移动
// - 基于原来的位置移动,而不是把view的center带到了鼠标点击的位置
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// > 先记录下点击当前视图的位置
// * 获取点击的位置的坐标:通过方法传递过来的形参获取
CGPoint clickPoint = [[touches anyObject] locationInView:self];
// * 获取的坐标是相同的
//[[touches anyObject] previousLocationInView:self];
// > 保存主视图的中心点和鼠标点击位置的差值
_plusPoint.x = _Pview.center.x - clickPoint.x;
_plusPoint.y = _Pview.center.y - clickPoint.y;
// 3.通过保存的对象和SEL:在touchesBegin时使用该对象调用该包装的方法
// 注意:是调用被打包的方法,即点击view后传递过来的方法;而不是该类中自定义的事件
[self.sender performSelector:self.action];
// 4.代理:在点击view时让view显示属性(字符串):系统的TouchesBegin事件触发时
// - 判断代理是否为空
if (self.delegate!=nil)
{
// 判断代理是否实现了协议内方法
if ([self.delegate respondsToSelector:@selector(touchesPPVoewBegin:)])
{
// >复合是思想:代理被使用代理的类所复合,通过代理调用了代理遵循的方法
// > 确保传递出去的形参可以访问属性:谁触发就把谁传递出去
[self.delegate touchesPPVoewBegin:self];
}
}else
{
NSLog(@"delegate = nil");
}
}
// - 让鼠标的移动和子视图的距离变得固定
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
CGPoint clickPoint = [[touches anyObject] locationInView:self];
// > 保存鼠标点击父视图上的位置:这个值是不断变化的
_Pview.center = (CGPoint){clickPoint.x+_plusPoint.x, clickPoint.y+_plusPoint.y};
}
// 3.在view上实现了button的效果
// - 触发事件时就保存了传递过来的对象和被打包的方法
- (void)addTarget:(id)target andAction:(SEL)action
{
// - 代码加载完毕,通过方法实现保存了该对象和需要调用的SEL
self.sender = target;
self.action = action;
}
关于iOS自定义控件:在view上实现事件和代理的更多相关文章
- iOS 自定义控件开发(上)
工作需要,最近在进行iOS方面的图表工作.找了很多第三方库都无法实现效果,所以决定自己写一个控件. <iOS 自定义控件开发(上)> <iOS 自定义控件开发(中)> #0 目 ...
- iOS 自定义控件开发(中)
<iOS 自定义控件开发(上)> <iOS 自定义控件开发(中)> 接上篇iOS自定义控件开发之后,我们尝试另外一种. 在Xcode的右边,会看到如下的图 其中,上面有一个:C ...
- android view、viewgroup 事件响应拦截处理机制
文章中会用到部分网络资源,首先将原作者的链接附上. 但是还是会附上数量较大的关于此部分内容的自己的思考. ----------------------------------------------- ...
- view上添加点手势 button无法响应点击事件
在view 上添加手势 有的时候 会把Button的 点击事件盖掉,这个 时候 我们用UITapGestureRecognizer的代理方法 //手势的代理方法 - (BOOL)gestureRec ...
- AJ学IOS 之控制器view显示中view的父子关系及controller的父子关系_解决屏幕旋转不能传递事件问题
AJ分享,必须精品 一:效果 二:项目代码 这个Demo用的几个控制器分别画了不通的xib,随便拖拽了几个空间,主要是几个按钮的切换,主要代码展示下: // // NYViewController.m ...
- iOS constraint被应用于view上的时间
在viewdidload时,constraint是没有被应用的,之后在layoutSubviews时,系统应用了constraint.但是我感觉在viewWillLayoutSubviews函数时就已 ...
- iOS自定义控件教程:制作一个可重用的旋钮
当你的APP需要一些新功能时,自定义UI控件会十分有用,尤其是这些自定义控件可以在其他APP里面很好的重用.Colin Eberhart写过一篇很棒的介绍自定义UI控件的教程.这个教程涉及的是一个继承 ...
- iOS 开发总结(上)
来源:蝴蝶之梦天使 链接:http://www.jianshu.com/p/d333cf6ae4b0 在iOS开发中经常需要使用的或不常用的知识点的总结,几年的收藏和积累(踩过的坑). 一. iPho ...
- [iOS UI进阶 - 3.1] 触摸事件的传递
A.事件的产生和传递 发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常,先发 ...
随机推荐
- nginx libpcre.so.1: cannot open shared object file
linux 64位安装nginx后启动出错报以下错误 1 2 3 [root@localhost nginx-1.3.0]# /usr/local/nginx/sbin/nginx error whi ...
- Linq skip skipwhile take takewhile
一.Skip()跳过 static void Main(string[] args) { //skip()跳过 ,,,,,,,,,}; //跳过3条 nums.Skip().ToList().ForE ...
- C# 截取字符串某个字符分割的最后一部分
例如 string s1="123.456.789",想截取得到的新字符串为“789” 代码如下: string s1 = "123.456.789"; str ...
- 1.1 mysql安装
直接百度mysql 即可下载.. 下载完毕之后是压缩包,解压缩即可 解压之后可以将该文件夹改名,放到合适的位置,个人建议把文件夹改名为MySQL Server 5.6,放到D:\MySQL Serve ...
- 【dp】 poj 1157
不错的dp入门题 画出dp矩阵 每个dp[i][j]是由“其上”的状态或是“其左上”的状态转化而来,那我们选对角线和上边进行三角dp推导 #include<stdio.h> #incl ...
- GDT、GDTR、LDT、LDTR的理解
GDT是全局描述附表,主要存放操作系统和各任务公用的描述符,如公用的数据和代码段描述符.各任务的TSS描述符和LDT描述符.(TSS是任务状态段,存放各个任务私有运行状态信息描述符)LDT是局部描述符 ...
- group_concat()函数总结
group_concat(),手册上说明:该函数返回带有来自一个组的连接的非NULL值的字符串结果.比较抽象,难以理解. 通俗点理解,其实是这样的:group_concat()会计算哪些行属于同一组, ...
- DEAMONTOOLS: installation
installing daemontools .. adding -I /usr/include/errno.h to last first line of conf-cc mkdir -p /pac ...
- C --> OC with RunTime
前言 本来打算写一篇关于runtime的学习总结,无奈长篇大论不是我的风格,就像写申论一样痛苦,加之网上关于tuntime的文章多如牛毛,应该也够童子们学习的了,今天就随便聊聊我的理解吧. runti ...
- Swift 与 JSON 数据 浅析
转载自:http://www.cnblogs.com/theswiftworld/p/4660177.html 我们大家平时在开发 App 的时候,相信接触最多的就是 JSON 数据了.只要你的 Ap ...