前言:
很多社交軟件,都需要用戶上傳頭像等很多照片,因此上傳照片時的交互體驗尤為重要,這里就簡述一下探探照片拖拽排序的實現方法。
思路:
這里裝載圖片的控件我們使用UIButton
給每個圖片控件UIButton添加滑動手勢,在拖拽的過程中通過“碰撞檢測”實現兩個控件坐標CGPoint和CGRect的交換。
核心代碼:
#pragma mark - 拖拽事件
-(void)pan:(UIPanGestureRecognizer*)recognizer{
Button *recognizerView = (Button *)recognizer.view;
//獲取移動偏移量
CGPoint recognizerPoint = [recognizer translationInView:self.view];
if (recognizer.state == UIGestureRecognizerStateBegan) {
if (recognizerView.selected == NO) {
}else{
//開始的時候改變拖動view的外觀(放大,改變顏色等)
[UIView animateWithDuration:0.2 animations:^{
if (recognizerView.tag == 100) {
recognizerView.transform = CGAffineTransformMakeScale(0.35, 0.35);
}else{
recognizerView.transform = CGAffineTransformMakeScale(0.75, 0.75);
}
recognizerView.alpha = 0.7;
}];
//把拖動view放到最上層
[self.view bringSubviewToFront:recognizerView];
//valuePoint保存最新的移動位置
valuePoint = recognizerView.center;
}
CGFloat btnWidth = (Screen_Width - autolyout(9)) / 4;
CGFloat headericonheight = Screen_Width - btnWidth - autolyout(3);
if (recognizerView.tag == 100) {
valueFrame =CGRectMake(0, 0, headericonheight, headericonheight);
}else{
valueFrame = CGRectMake(0, 0, btnWidth, btnWidth);
}
}else if(recognizer.state == UIGestureRecognizerStateChanged){
//更新pan.view的center
CGFloat x = recognizerView.center.x + recognizerPoint.x;
CGFloat y = recognizerView.center.y + recognizerPoint.y;
if (recognizerView.selected == YES) {
recognizerView.center = CGPointMake(x, y);
}
//因為拖動會持續執行 所以每次結束都要清空
[recognizer setTranslation:CGPointZero inView:self.view];
for (Button * bt in contain.subviews) {
//判斷是否移動到另一個view區域
//CGRectContainsPoint(rect,point)
//判斷某個點是否被某個frame包含
if (CGRectContainsPoint(bt.frame, recognizerView.center)&&bt!=recognizerView){
//開始位置
NSInteger fromIndex = recognizerView.tag - KBase_tag;
//需要移動到的位置
NSInteger toIndex = bt.tag - KBase_tag;
//往后移動
if ((toIndex-fromIndex)>0) {
//從開始位置移動到結束位置
//把移動view的下一個view移動到記錄的view的位置(valuePoint),并把下一view的位置記為新的nextPoint,并把view的tag值-1,依次類推
if (bt.selected == NO||recognizerView.selected == NO) {
}else{
[UIView animateWithDuration:0.2 animations:^{
for (NSInteger i = fromIndex+1; i<=toIndex; i++) {
Button * nextBt = (Button*)[self.view viewWithTag:KBase_tag+i];
nextFrame = nextBt.frame;
nextPoint = nextBt.center;
nextBt.frame = valueFrame;
nextBt.center = valuePoint;
valueFrame = nextFrame;
valuePoint = nextPoint;
nextBt.tag--;
}
recognizerView.tag = KBase_tag + toIndex;
}];
}
}
//往前移動
else{
//從開始位置移動到結束位置
//把移動view的上一個view移動到記錄的view的位置(valuePoint),并把上一view的位置記為新的nextPoint,并把view的tag值+1,依次類推
if (bt.selected == NO||recognizerView.selected == NO) {
}else{
[UIView animateWithDuration:0.2 animations:^{
for (NSInteger i = fromIndex-1; i>=toIndex; i--) {
Button * nextBt = (Button*)[self.view viewWithTag:KBase_tag+i];
nextFrame = nextBt.frame;
nextPoint = nextBt.center;
nextBt.frame = valueFrame;
nextBt.center = valuePoint;
valueFrame = nextFrame;
valuePoint = nextPoint;
nextBt.tag++;
}
recognizerView.tag = KBase_tag + toIndex;
}];
}
}
}
}
}else if(recognizer.state == UIGestureRecognizerStateEnded){
if (recognizerView.selected == YES) {
//結束時候恢復view的外觀(放大,改變顏色等)
[UIView animateWithDuration:0.2 animations:^{
recognizerView.transform = CGAffineTransformMakeScale(1.0, 1.0);
recognizerView.alpha = 1;
recognizerView.frame = valueFrame;
recognizerView.center = valuePoint;
[self photosDataRanking];
}];
}
}
}
這樣就完成了控件之間的拖拽后的互換,但是新的問題又來了,如果涉及到網絡上傳,空間上的圖片肯定是放到一個數組里面,如何在控件互換的時候數組里面的圖片索引頁跟著互換呢?如果涉及到刪除空間上的圖片并且依次重新排序怎么實現呢?
有些新入行的同學一定會這樣想,給每個UIButton控件編號,控件交換的過程中,通過編號聯系到數組索引,同步數組中圖片也交換,刪除某個編號控件上的圖片,數組就刪除哪一個索引的圖片。
但是這樣數組的聯動,未免太過于復雜,而且代碼似乎并不好看,這里給大家分享下我的思路,不喜勿噴。
第一步:
自定義一個UIButton 帶有UIImage屬性
#import@interface Button : UIButton
@property (nonatomic,strong)UIImage *image;
@end
第二步:
每一次拖拽互換的時候調用排序方法
#pragma mark - 圖片數據重新排列
-(void)photosDataRanking{
[photos removeAllObjects];
for (int i = 0; i < PhotosNum; i ++) {
Button *btn = [self.view viewWithTag:100 + i];
[photos addObject:btn.image];
}
}
完成這兩步,圖片控件拖拽同時圖片數組的重新排序的需求就完成了。
還差最后一步就是刪除時候 圖片數組的重新排序:
因為我寫代碼是考慮到本身控件有占位圖片的,所以單獨又寫了一個方法,如果沒有占位圖片,可以在上面排序的方法中 實現邏輯
//刪除照片
[photos removeObject:sender.image];
//重新排序
[self photosRanking];
#pragma mark - 圖片UI重新排列(刪除照片 添加照片的時候調用)
-(void)photosRanking{
for (int i = 0; i < 8; i ++) {
Button *btn = [self.view viewWithTag:100 + i];
if (i < photos.count) {//有照片的 按鈕狀態變成有照片
btn.image = photos[i];
[btn setImage:photos[i] forState:UIControlStateNormal];
btn.selected = YES;
}else{//沒照片 按鈕狀態變成沒照片
if (i == 0) {
btn.selected = NO;
[btn setImage:[UIImage imageNamed:@"headerUpdata"] forState:UIControlStateNormal];
}else{
btn.selected = NO;
[btn setImage:[UIImage imageNamed:@"photoAdd"] forState:UIControlStateNormal];
}
}
}
}
總結
我在github上面上傳了demo,有需求的同學可以自己下載研究,代碼簡單,清晰易懂。----》》? JimmyPicEditor