我目前正在为一个应用创建一个视图控制器,以帮助可视化Bubble Sort算法。但是,当用户按下排序按钮时,不是一次接一个地进行交换(给用户一些时间来查看算法的工作原理),而是数字一次全部排序,并且它们一次都转到各自的位置。我希望让UIAnimation遍历for循环,并使元素一次一交换,而不是一次全部交换。
我已经尝试过将延迟作为参数传递给UIView.animate方法。它所做的只是在将它们全部排序之前暂停指定的时间(我不想要)。
//IBOutlets for the images (containing numbers) and the sort button
@IBOutlet weak var sortButton: UIButton!
@IBOutlet weak var firstImage: UIImageView!
@IBOutlet weak var secondImage: UIImageView!
@IBOutlet weak var thirdImage: UIImageView!
@IBOutlet weak var fourthImage: UIImageView!
@IBOutlet weak var fifthImage: UIImageView!
@IBOutlet weak var sixthImage: UIImageView!
@IBOutlet weak var seventhImage: UIImageView!
@IBOutlet weak var eighthImage: UIImageView!
@IBOutlet weak var ninthImage: UIImageView!
@IBOutlet weak var tenthImage: UIImageView!
//Create an array of UIImageViews
var elements : [UIImageView] = [UIImageView]()
var numberArray : [Int] = [Int]()
//Function when the view loads
override func viewDidLoad() {
super.viewDidLoad()
//Add the UIImageViews to the array
elements += [firstImage, secondImage, thirdImage, fourthImage, fifthImage, sixthImage, seventhImage, eighthImage, ninthImage, tenthImage]
//Create a variable that will indicate whether there is a duplicate number in the array
var duplicate = true;
//Assign each element in the array a random number between 1 and 10
for index in elements {
//Repeat-while loop to avoid duplicate numbers in the array
repeat {
//Create a random number
let randNumber = Int.random(in: 1 ... 10)
//Display the appropriate numbered image
index.image = UIImage(named: "\(randNumber)")
//Check to see if the number is already a duplicate
if numberArray.contains(randNumber) {
duplicate = true
} else {
duplicate = false
//Add the number to the list of used numbers in the array
numberArray.append(randNumber)
}
} while duplicate == true
}
} //End of viewDidLoad
@IBAction func sortButtonPressed(_ sender: Any) {
//Bubble Sort algorithm
for i in (0..<elements.count) {
for j in (1..<elements.count) {
if numberArray[j]<numberArray[j-1] {
let temp = numberArray[j-1]
numberArray[j-1] = numberArray[j]
numberArray[j] = temp
let tempElement = elements[j-1]
elements[j-1] = elements[j]
elements[j] = tempElement
//Swap the corresponding UIImageViews on screen
let tempView : CGRect = elements[j-1].frame
UIView.animate(withDuration: 0.75, delay: 0, animations: {
self.elements[j-1].frame = CGRect(x: self.elements[j].frame.minX, y: self.elements[j].frame.minY, width: tempView.width, height: tempView.height)
self.elements[j].frame = CGRect(x: tempView.minX, y: tempView.minY, width: self.elements[j].frame.width, height: self.elements[j].frame.width)
self.view.layoutIfNeeded()
})
}
}
}
}
有人知道如何使图像交换(动画)一次(每次迭代)而不是一次全部发生吗? (焦点区域位于sortButtonPressed函数的底部...)任何帮助将不胜感激。感谢您的提前帮助!
答案 0 :(得分:0)
要手动执行此操作,您需要在当前动画完成后开始一个新动画。这样做的方法很少,但其中一种方法是将动画所需的所有数据打包到一个类中,然后创建此类数组。然后,您可以创建一个递归调用的方法。像这样:
- (void)performAllAnimations:(NSArray *)allAnimations
{
NSMutableArray *duplicate = [allAnimations mutableCopy];
AnimationDescription *currentAnimation = duplicate.firstObject;
[duplicate removeObjectAtIndex:0];
[UIView animateWithDuration:currentAnimation.duration animations:^{
// Use currentAnimation to do the animation
} completion:^(BOOL finished) {
if(duplicate.count > 0) [self performAllAnimations:duplicate];
}];
}
您不一定总是需要AnimationDescription
作为自定义类。在您的情况下,仅使用索引数组就足够了。例如,您将这样做:
- (void)performAllAnimations:(NSArray *)allAnimations
{
NSMutableArray *duplicate = [allAnimations mutableCopy];
int currentAnimationIndex = [duplicate.firstObject integerValue];
[duplicate removeObjectAtIndex:0];
[UIView animateWithDuration:0.3 animations:^{
// Use currentAnimation to do the animation
} completion:^(BOOL finished) {
if(duplicate.count > 0) [self performAllAnimations:duplicate];
}];
}
然后您可以执行以下操作:
NSMutableArray *indexArray = [[NSMutableArray alloc] init];
for(int i=0; i<10; i++) {
[indexArray addObject:@(i)];
}
[self performAllAnimations: indexArray];
自然使用您自己的数据。
另一种方法是使用延迟。在某些情况下,这可能会更好,因为您可以更好地控制下一个动画的开始时间。请参见以下示例:
- (void)performAllAnimations:(NSArray *)allAnimations withAnimationExecution:(void (^)(id animationObject, int index))execution
{
NSTimeInterval duration = 0.3;
for(int i=0; i<allAnimations.count; i++) {
[UIView animateWithDuration:duration delay:(duration*0.5)*i options:UIViewAnimationOptionCurveEaseInOut animations:^{
execution(allAnimations[i], i);
} completion:^(BOOL finished) {
}];
}
}
- (void)testAnimation
{
NSMutableArray *views = [[NSMutableArray alloc] init];
for(int i=0; i<10; i++) {
UIView *aView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 50.0, 100.0, 100.0)];
[self.view addSubview:aView];
aView.backgroundColor = [UIColor blackColor];
aView.layer.borderWidth = 2.0;
aView.layer.borderColor = [UIColor yellowColor].CGColor;
[views addObject:aView];
}
[self performAllAnimations:views withAnimationExecution:^(id animationObject, int index) {
UIView *view = animationObject;
view.frame = CGRectMake(75.0*index, 100.0, 100.0, 100.0);
}];
}