http://www.itnose.net/news/155/6429874
这是一个完全依靠手势的 *** 作TodoList的演示,功能上左划删除,右划完成任务,拖拽调整顺序,捏合张开插入。
项目源码: https://github.com/luan-ma/ClearStyleDemo.Swift
初始化
TDCTodoItem.swift 定义模型对象
TDCTodoListController.swift 继承自UItableVIEwController, 演示UItableVIEw *** 作
varitems=[TDCTodoItem(text:"Feedthecat"),TDCTodoItem(text:"Buyeggs"),TDCTodoItem(text:"PackbagsforWWDC"),TDCTodoItem(text:"Ruletheweb"),TDCTodoItem(text:"BuyanewiPhone"),TDCTodoItem(text:"Findmissingsocks"),TDCTodoItem(text:"Writeanewtutorial"),TDCTodoItem(text:"MasterObjective-C"),TDCTodoItem(text:"Rememberyourweddinganniversary!"),TDCTodoItem(text:"Drinklessbeer"),TDCTodoItem(text:"Learntodraw"),TDCTodoItem(text:"Takethecartothegarage"),TDCTodoItem(text:"SellthingsoneBay"),TDCTodoItem(text:"Learntojuggle"),TDCTodoItem(text:"Giveup")]overrIDefuncvIEwDIDLoad(){super.vIEwDIDLoad()//捏合手势letpinch=UIPinchGestureRecognizer(target:self,action:"handlePinch:")//长按拖拽letlongPress=UILongPressGestureRecognizer(target:self,action:"handleLongPress:")tableVIEw.addGestureRecognizer(pinch)tableVIEw.addGestureRecognizer(longPress)}
在每一个Cell添加滑动手势(Pan)。处理划动距离,超过宽度1/3就为有效 *** 作,左划为删除 *** 作,右划为完成 *** 作。
布局使用autoLayout,中间内容区的限制条件是宽度等于容器宽度、高度等于容器高度、垂直中对齐、水平中对齐,而平移 *** 作实际上就是 *** 作水平中对齐的距离值。
TDCTodoItemCell.swift关键代码如下
手势判断
//如果是划动手势,仅支持左右划动;如果是其它手势,则有父类负责overrIDefuncgestureRecognizerShouldBegin(gestureRecognizer:UIGestureRecognizer)->Bool{ifletpanGesture=gestureRecognizeras?UIPanGestureRecognizer{lettranslation=panGesture.translationInVIEw(self.supervIEw)returnfabs(translation.x)>fabs(translation.y)}else{returnsuper.gestureRecognizerShouldBegin(gestureRecognizer)}}
varonDelete:((TDCTodoItemCell)->VoID)?varonComplete:((TDCTodoItemCell)->VoID)?privatevardeleteOnDragrelease:Bool=falseprivatevarcompleteOnDragrelease:Bool=false//划动平移的实际autoLayout中的水平中对齐的距离@IBOutletweakvarcenterConstraint:NSLayoutConstraint!privatevaroriginConstant:CGfloat=0funchandlePan(panGesture:UIPanGestureRecognizer){switchpanGesture.state{case.Began:originConstant=centerConstraint.constantcase.Changed:lettranslation=panGesture.translationInVIEw(self)centerConstraint.constant=translation.x//划动移动1/3宽度为有效划动letfinished=fabs(translation.x)>CGRectGetWIDth(bounds)/3iftranslation.x<originConstant{//右划iffinished{deleteOnDragrelease=truerightLabel.textcolor=UIcolor.redcolor()}else{deleteOnDragrelease=falserightLabel.textcolor=UIcolor.whitecolor()}}else{//左划iffinished{completeOnDragrelease=trueleftLabel.textcolor=UIcolor.greencolor()}else{completeOnDragrelease=falseleftLabel.textcolor=UIcolor.whitecolor()}}case.Ended:centerConstraint.constant=originConstantifdeleteOnDragrelease{deleteOnDragrelease=falseifletonDelete=onDelete{onDelete(self)}}ifcompleteOnDragrelease{completeOnDragrelease=falseifletonComplete=onComplete{onComplete(self)}}default:break}}
在TDCTodoListController.swift中执行删除 *** 作
/*//简单删除funcdeletetoDoItem(indexPath:NSIndexPath){tableVIEw.beginUpdates()items.removeAtIndex(indexPath.row)tableVIEw.deleteRowsAtIndexPaths([indexPath],withRowAnimation:.automatic)tableVIEw.endUpdates()}*///视觉效果更漂亮的删除funcdeletetoDoItem(indexPath:NSIndexPath){letitem=items.removeAtIndex(indexPath.row)varanimationEnabled=falseletlastCell=tableVIEw.visibleCells.lastvardelay:NSTimeInterval=0forcellintableVIEw.visibleCells{letcell=cellas!TDCTodoItemCellifanimationEnabled{UIVIEw.animateWithDuration(0.25,delay:delay,options:.CurveEaseInOut,animations:{()->VoIDincell.frame=CGRectOffset(cell.frame,-CGRectGetHeight(cell.frame))},completion:{(completed)->VoIDinifcell==lastCell{self.tableVIEw.reloadData()}})delay+=0.03}ifcell.todoItem==item{animationEnabled=truecell.hIDden=true}}}
长按选中某Cell,截图此Cell生成UIImageVIEw,然后隐藏此Cell(hIDden=true),随手指移动拖拽UIImageVIEw,每次拖拽到一个Cell上的时候,交换当前Cell和隐藏Cell位置。效果如下
截图UIVIEw生成一个新的UIImageVIEw
funcsnapVIEw(vIEw:UIVIEw)->UIImageVIEw{UIGraphicsBeginImageContextWithOptions(vIEw.bounds.size,false,0)vIEw.layer.renderInContext(UIGraphicsGetCurrentContext()!)letimage=UIGraphicsGetimageFromCurrentimageContext()UIGraphicsEndImageContext()letsnapShot=UIImageVIEw(image:image)snapShot.layer.masksToBounds=false;snapShot.layer.cornerRadius=0;snapShot.layer.shadowOffset=CGSizeMake(-5.0,0.0);snapShot.layer.shadowOpacity=0.4;snapShot.layer.shadowRadius=5;snapShot.frame=vIEw.framereturnsnapShot}
拖拽 *** 作代码,详细 *** 作参考注释
privatevarsourceIndexPath:NSIndexPath?privatevarsnapVIEw:UIVIEw?funchandleLongPress(longPress:UILongPressGestureRecognizer){letpoint=longPress.locationInVIEw(tableVIEw)ifletindexPath=tableVIEw.indexPathForRowAtPoint(point){switchlongPress.state{case.Began:ifletcell=tableVIEw.cellForRowAtIndexPath(indexPath){sourceIndexPath=indexPathletsnapVIEw=self.snapVIEw(cell)snapVIEw.Alpha=0self.snapVIEw=snapVIEwtableVIEw.addSubvIEw(snapVIEw)UIVIEw.animateWithDuration(0.25,animations:{//选中Cell跳出放大效果snapVIEw.Alpha=0.95snapVIEw.center=CGPointMake(cell.center.x,point.y)snapVIEw.transform=CGAffinetransformMakeScale(1.05,1.05)cell.Alpha=0},completion:{(completed)->VoIDincell.hIDden=truecell.Alpha=1})}else{sourceIndexPath=nilsnapVIEw=nilbreak}case.Changed:ifletsnapVIEw=snapVIEw{//截图随手指上下移动snapVIEw.center=CGPointMake(snapVIEw.center.x,point.y)}//如果手指移动到一个新的Cell上面,隐藏Cell跟此Cell交换位置ifletfromIndexPath=sourceIndexPath{iffromIndexPath!=indexPath{tableVIEw.beginUpdates()lettemp=items[indexPath.row]items[indexPath.row]=items[fromIndexPath.row]items[fromIndexPath.row]=temptableVIEw.moveRowAtIndexPath(fromIndexPath,toIndexPath:indexPath)tableVIEw.endUpdates()sourceIndexPath=indexPath}}//手指移动到屏幕顶端或底部,UItableVIEw自动滚动letstep:CGfloat=64ifletparentVIEw=tableVIEw.supervIEw{letparentPos=tableVIEw.convertPoint(point,toVIEw:parentVIEw)ifparentPos.y>parentVIEw.bounds.height-step{varoffset=tableVIEw.contentOffsetoffset.y+=(parentPos.y-parentVIEw.bounds.height+step)ifoffset.y>tableVIEw.contentSize.height-tableVIEw.bounds.height{offset.y=tableVIEw.contentSize.height-tableVIEw.bounds.height}tableVIEw.setContentOffset(offset,animated:false)}elseifparentPos.y<=step{varoffset=tableVIEw.contentOffsetoffset.y-=(step-parentPos.y)ifoffset.y<0{offset.y=0}tableVIEw.setContentOffset(offset,animated:false)}}default:ifletsnapVIEw=snapVIEw,letfromIndexPath=sourceIndexPath,letcell=tableVIEw.cellForRowAtIndexPath(fromIndexPath){cell.Alpha=0cell.hIDden=false//长按移动结束,隐藏的Cell恢复显示,删除截图UIVIEw.animateWithDuration(0.25,animations:{()->VoIDinsnapVIEw.center=cell.centersnapVIEw.Alpha=0cell.Alpha=1},completion:{[uNownedself](completed)->VoIDinsnapVIEw.removeFromSupervIEw()self.snapVIEw=nilself.sourceIndexPath=nilself.tableVIEw.performSelector("reloadData",withObject:nil,afterDelay:0.5)})}}}}
通过捏合手势中两个触点获取两个相邻的Cell,通过修改UIVIEw.transform属性移动屏幕上的Cell位置。
获取Pinch两个手指坐标的工具方法
funcpointsOfPinch(pinch:UIPinchGestureRecognizer)->(CGPoint,CGPoint){ifpinch.numberOftouches()>1{letpoint1=pinch.locationOftouch(0,inVIEw:tableVIEw)letpoint2=pinch.locationOftouch(1,inVIEw:tableVIEw)ifpoint1.y<=point2.y{return(point1,point2)}else{return(point2,point1)}}else{letpoint=pinch.locationOftouch(0,inVIEw:tableVIEw)return(point,point)}}
捏合张开 *** 作代码,详情请参考代码和注释
//插入点privatevarpinchIndexPath:NSIndexPath?//临时代理视图privatevarplacheHolderCell:TDCPlaceHolderVIEw?//两触点的起始位置privatevarsourcePoints:(upperPoint:CGPoint,downPoint:CGPoint)?//可以插入 *** 作的标志privatevarpinchInsertEnabled=falsefunchandlePinch(pinch:UIPinchGestureRecognizer){switchpinch.state{case.Began:pinchBegan(pinch)case.Changed:pinchChanged(pinch)default:pinchEnd(pinch)}}funcpinchBegan(pinch:UIPinchGestureRecognizer){pinchIndexPath=nilsourcePoints=nilpinchInsertEnabled=falselet(upperPoint,downPoint)=pointsOfPinch(pinch)ifletupperIndexPath=tableVIEw.indexPathForRowAtPoint(upperPoint),letdownIndexPath=tableVIEw.indexPathForRowAtPoint(downPoint){ifdownIndexPath.row-upperIndexPath.row==1{letupperCell=tableVIEw.cellForRowAtIndexPath(upperIndexPath)!letplacheHolder=NSBundle.mainBundle().loadNibnamed("TDCPlaceHolderVIEw",owner:tableVIEw,options:nil).firstas!TDCPlaceHolderVIEwplacheHolder.frame=CGRectOffset(upperCell.frame,CGRectGetHeight(upperCell.frame)/2)tableVIEw.insertSubvIEw(placheHolder,atIndex:0)sourcePoints=(upperPoint,downPoint)pinchIndexPath=upperIndexPathplacheHolderCell=placheHolder}}}funcpinchChanged(pinch:UIPinchGestureRecognizer){ifletpinchIndexPath=pinchIndexPath,letoriginPoints=sourcePoints,letplacheHolderCell=placheHolderCell{letpoints=pointsOfPinch(pinch)letupperdistance=points.0.y-originPoints.upperPoint.yletdowndistance=originPoints.downPoint.y-points.1.yletdistance=-min(0,min(upperdistance,downdistance))NSLog("distance=\(distance)")//移动两边的CellforcellintableVIEw.visibleCells{letindexPath=tableVIEw.indexPathForCell(cell)!ifindexPath.row<=pinchIndexPath.row{cell.transform=CGAffinetransformMakeTranslation(0,-distance)}else{cell.transform=CGAffinetransformMakeTranslation(0,distance)}}//插入的Cell变形letscaleY=min(64,fabs(distance)*2)/CGfloat(64)placheHolderCell.transform=CGAffinetransformMakeScale(1,scaleY)placheHolderCell.lblTitle.text=scaleY<=0.5?"张开双指插入新项目":"松手可以插入新项目"//张开超过一个Cell高度时,执行插入 *** 作pinchInsertEnabled=scaleY>=1}}funcpinchEnd(pinch:UIPinchGestureRecognizer){ifletpinchIndexPath=pinchIndexPath,letplacheHolderCell=placheHolderCell{placheHolderCell.transform=CGAffinetransformIDentityplacheHolderCell.removeFromSupervIEw()self.placheHolderCell=nilifpinchInsertEnabled{//恢复各Cell的transformforcellinself.tableVIEw.visibleCells{cell.transform=CGAffinetransformIDentity}//插入 *** 作letindex=pinchIndexPath.row+1items.insert(TDCTodoItem(text:""),atIndex:index)tableVIEw.reloadData()//d出键盘letcell=tableVIEw.cellForRowAtIndexPath(NSIndexPath(forRow:index,inSection:0))as!TDCTodoItemCellcell.txtFIEld.becomeFirstResponder()}else{//放弃插入,恢复原位置UIVIEw.animateWithDuration(0.25,delay:0,animations:{[uNownedself]()->VoIDinforcellinself.tableVIEw.visibleCells{cell.transform=CGAffinetransformIDentity}},completion:{[uNownedself](completed)->VoIDinself.tableVIEw.reloadData()})}}sourcePoints=nilpinchIndexPath=nilpinchInsertEnabled=false}
1. https://github.com/ColinEberhardt/iOS-ClearStyle
2. http://blog.csdn.net/u013604612/article/details/43884039
总结以上是内存溢出为你收集整理的Swift语言开发:仿Clear手势 *** 作(拖拽、划动、捏合)UITableView全部内容,希望文章能够帮你解决Swift语言开发:仿Clear手势 *** 作(拖拽、划动、捏合)UITableView所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)