我做了一个小测试,将 UIScrollView 中的视图拖到 UIView 中,我可以在其中调用任何操作。
我正在尝试制作我在 UIScrollView Draggable 中制作的图像。我无法完成这项工作。
我能够创建不是能够拖动的图像的测试视图。
测试视图控制器.h
#import "JDDroppableView.h"
@interface TestViewController : UIViewController <JDDroppableViewDelegate>
{
UIScrollView* mScrollView;
UIView* mDropTarget;
UIImageView *images;
UIImageView *image;
CGPoint mLastPosition;
}
- (void) relayout;
- (void) addView: (id) sender;
- (void) scrollToBottomAnimated: (BOOL) animated;
@property (nonatomic, retain) IBOutlet UIImageView *images;
@property (nonatomic, retain) IBOutlet UIImageView *image;
@end
测试视图控制器.m
#import "TestViewController.h"
#import "JDDroppableView.h"
#import <QuartzCore/QuartzCore.h>
// setup view vars
static NSInteger sDROPVIEW_MARGIN = 3;
static CGFloat sCOUNT_OF_VIEWS_HORICONTALLY = 1.0;
static CGFloat sCOUNT_OF_VIEWS_VERTICALLY = 1.0;
@implementation TestViewController
@synthesize images;
@synthesize image;
- (void)loadView
{
[super loadView];
self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor];
// increase viewcount on ipad
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
sCOUNT_OF_VIEWS_HORICONTALLY = 0;
sCOUNT_OF_VIEWS_VERTICALLY = 0;
}
// add button
UIButton* button = [UIButton buttonWithType: UIButtonTypeCustom];
[button setImage:[UIImage imageNamed:@"002.jpg"] forState:UIControlStateNormal];
button.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
[button setTitle: @"+" forState: UIControlStateNormal];
[button addTarget: self action: @selector(addView:) forControlEvents: UIControlEventTouchUpInside];
button.backgroundColor = [UIColor colorWithRed: 0.75 green: 0.2 blue: 0 alpha: 1.0];
button.layer.cornerRadius = 5.0;
button.showsTouchWhenHighlighted = YES;
button.adjustsImageWhenHighlighted = YES;
button.frame = CGRectMake(20,
self.view.frame.size.height - 52,
self.view.frame.size.width - 40, // width
32); // height
[self.view addSubview: button];
// drop target
mDropTarget = [[UIView alloc] init];
mDropTarget.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
mDropTarget.backgroundColor = [UIColor orangeColor];
mDropTarget.frame = CGRectMake(0, 0, 30, 30);
mDropTarget.center = CGPointMake(self.view.frame.size.width/2, button.frame.origin.y - 50);
mDropTarget.layer.cornerRadius = 15;
[self.view addSubview: mDropTarget];
[mDropTarget release];
// scrollview
mScrollView = [[UIScrollView alloc] init];
mScrollView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
mScrollView.backgroundColor = [UIColor colorWithRed: 0.75 green: 0.2 blue: 0 alpha: 1.0];
mScrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
mScrollView.scrollIndicatorInsets = UIEdgeInsetsMake(5, 5, 5, 5);
mScrollView.contentInset = UIEdgeInsetsMake(6, 6, 6, 6);
mScrollView.layer.cornerRadius = 5.0;
mScrollView.frame = CGRectMake(20,20, self.view.frame.size.width - 40, mDropTarget.center.y - 70);
mScrollView.userInteractionEnabled = NO;
mScrollView.canCancelContentTouches = NO;
[self.view addSubview: mScrollView];
[mScrollView release];
// animate some draggable views in
int numberOfViews = sCOUNT_OF_VIEWS_HORICONTALLY*floor(sCOUNT_OF_VIEWS_VERTICALLY) + 2;
CGFloat animationTimePerView = 0.15;
for (int i = 0; i < numberOfViews; i++) {
[self performSelector: @selector(addView:) withObject: nil afterDelay: i*animationTimePerView];
if (i%(int)sCOUNT_OF_VIEWS_HORICONTALLY==0) {
[self performSelector: @selector(scrollToBottomAnimated:) withObject: [NSNumber numberWithBool: YES] afterDelay: i*animationTimePerView];
}
}
CGRect myImageRect = CGRectMake(0, 0, 320, 100);
image = [[UIImageView alloc] initWithFrame:myImageRect];
[image setImage:[UIImage imageNamed:@"002.jpg"]];
[image setUserInteractionEnabled:YES];
[self.view addSubview:image];
[mScrollView addSubview:image];
// reenable userinteraction after animation ended
[mScrollView performSelector: @selector(setUserInteractionEnabled:) withObject: [NSNumber numberWithBool: YES] afterDelay: numberOfViews*animationTimePerView];
}
#pragma layout
- (void) relayout
{
// cancel all animations
[mScrollView.layer removeAllAnimations];
for (UIView* subview in mScrollView.subviews)
[subview.layer removeAllAnimations];
// setup new animation
[UIView beginAnimations: @"drag" context: nil];
// init calculation vars
float posx = 0;
float posy = 0;
CGRect frame = CGRectZero;
mLastPosition = CGPointMake(0, -100);
CGFloat contentWidth = mScrollView.contentSize.width - mScrollView.contentInset.left - mScrollView.contentInset.right;
// iterate through all subviews
for (UIView* subview in mScrollView.subviews)
{
// ignore scroll indicators
if (!subview.userInteractionEnabled) {
continue;
}
// create new position
frame = subview.frame;
frame.origin.x = posx;
frame.origin.y = posy;
// update frame (if it did change)
if (frame.origin.x != subview.frame.origin.x ||
frame.origin.y != subview.frame.origin.y) {
subview.frame = frame;
}
// save last position
mLastPosition = CGPointMake(posx, posy);
// add size and margin
posx += frame.size.width + sDROPVIEW_MARGIN;
// goto next row if needed
if (posx > mScrollView.frame.size.width - mScrollView.contentInset.left - mScrollView.contentInset.right)
{
posx = 0;
posy += frame.size.height + sDROPVIEW_MARGIN;
}
}
// fix last posy for correct contentSize
if (posx != 0) {
posy += frame.size.height;
} else {
posy -= sDROPVIEW_MARGIN;
}
// update content size
mScrollView.contentSize = CGSizeMake(contentWidth, posy);
[UIView commitAnimations];
}
- (void) addView: (id) sender
{
CGFloat contentWidth = mScrollView.frame.size.width - mScrollView.contentInset.left - mScrollView.contentInset.right;
CGFloat contentHeight = mScrollView.frame.size.height - mScrollView.contentInset.top;
CGSize size = CGSizeMake(((contentWidth-sDROPVIEW_MARGIN*(sCOUNT_OF_VIEWS_HORICONTALLY-1))/sCOUNT_OF_VIEWS_HORICONTALLY),
floor((contentHeight-sDROPVIEW_MARGIN*(sCOUNT_OF_VIEWS_VERTICALLY-1))/sCOUNT_OF_VIEWS_VERTICALLY));
JDDroppableView * dropview = [[JDDroppableView alloc] initWithDropTarget: mDropTarget];
dropview.backgroundColor = [UIColor blackColor];
dropview.layer.cornerRadius = 3.0;
dropview.frame = CGRectMake(mLastPosition.x, mLastPosition.y, size.width, size.height);
dropview.delegate = self;
[mScrollView addSubview: dropview];
[dropview release];
[self relayout];
// scroll to bottom, if added manually
if ([sender isKindOfClass: [UIButton class]]) {
[self scrollToBottomAnimated: YES];
}
}
- (void) scrollToBottomAnimated: (BOOL) animated
{
[mScrollView.layer removeAllAnimations];
CGFloat bottomScrollPosition = mScrollView.contentSize.height;
bottomScrollPosition -= mScrollView.frame.size.height;
bottomScrollPosition += mScrollView.contentInset.top;
bottomScrollPosition = MAX(-mScrollView.contentInset.top,bottomScrollPosition);
CGPoint newOffset = CGPointMake(-mScrollView.contentInset.left, bottomScrollPosition);
if (newOffset.y != mScrollView.contentOffset.y) {
[mScrollView setContentOffset: newOffset animated: animated];
}
}
#pragma -
#pragma droppabe view delegate
- (BOOL) shouldAnimateDroppableViewBack: (JDDroppableView *)view wasDroppedOnTarget: (UIView *)target
{
[self droppableView: view leftTarget: target];
CGRect frame = view.frame;
frame.size.width *= 0.3;
frame.size.height *= 0.3;
frame.origin.x += (view.frame.size.width-frame.size.width)/2;
frame.origin.y += (view.frame.size.height-frame.size.height)/2;
[UIView beginAnimations: @"drag" context: nil];
[UIView setAnimationDelegate: view];
[UIView setAnimationDidStopSelector: @selector(removeFromSuperview)];
view.frame = frame;
view.center = target.center;
[UIView commitAnimations];
[self relayout];
[mScrollView flashScrollIndicators];
return NO;
}
- (void) droppableViewBeganDragging:(JDDroppableView *)view
{
[UIView beginAnimations: @"drag" context: nil];
view.backgroundColor = [UIColor colorWithRed: 1 green: 0.5 blue: 0 alpha: 1];
view.alpha = 0.8;
[UIView commitAnimations];
}
- (void) droppableView:(JDDroppableView *)view enteredTarget:(UIView *)target
{
target.transform = CGAffineTransformMakeScale(1.5, 1.5);
target.backgroundColor = [UIColor greenColor];
// UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"image Collided"
// message:@"FuckYea"
// delegate:nil
// cancelButtonTitle:@"Reset!"
// otherButtonTitles:nil];
//[alert show];
CGRect myImageRect = CGRectMake(0, 0, 320, 100);
images = [[UIImageView alloc] initWithFrame:myImageRect];
[images setImage:[UIImage imageNamed:@"002.jpg"]];
[self.view addSubview:images];
}
- (void) droppableView:(JDDroppableView *)view leftTarget:(UIView *)target
{
target.transform = CGAffineTransformMakeScale(1.0, 1.0);
target.backgroundColor = [UIColor orangeColor];
}
- (void) droppableViewEndedDragging:(JDDroppableView *)view
{
[UIView beginAnimations: @"drag" context: nil];
view.backgroundColor = [UIColor blackColor];
view.alpha = 1.0;
[UIView commitAnimations];
}
@end
JDDroppableView.h
@class JDDroppableView;
@protocol JDDroppableViewDelegate <NSObject>
@optional
- (void) droppableViewBeganDragging: (JDDroppableView*) view;
- (void) droppableViewDidMove: (JDDroppableView*) view;
- (void) droppableView: (JDDroppableView*) view enteredTarget: (UIView*) target;
- (void) droppableView: (JDDroppableView*) view leftTarget: (UIView*) target;
- (BOOL) shouldAnimateDroppableViewBack: (JDDroppableView*) view wasDroppedOnTarget: (UIView*) target;
- (void) droppableViewEndedDragging: (JDDroppableView*) view;
@end
@interface JDDroppableView : UIView
{
UIView * mDropTarget;
UIView * mOuterView;
UIScrollView * mScrollView;
BOOL mIsDragging;
BOOL mIsOverTarget;
CGPoint mOriginalPosition;
}
@property (nonatomic, assign) id<JDDroppableViewDelegate> delegate;
- (id) initWithFrame:(CGRect)frame;
- (id) initWithDropTarget:(UIView*)target;
@end
JDDroppableView.m
#import "JDDroppableView.h"
@interface JDDroppableView (hidden)
- (void) beginDrag;
- (void) dragAtPosition: (UITouch *) touch;
- (void) endDrag;
- (void) changeSuperView;
- (BOOL) handleDroppedView;
@end
@implementation JDDroppableView
@synthesize delegate = _delegate;
- (id)init
{
return [self initWithFrame: [UIApplication sharedApplication].keyWindow.frame];
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
mIsDragging = NO;
mIsOverTarget = NO;
}
return self;
}
- (id) initWithDropTarget: (UIView *) target;
{
self = [self init];
if (self != nil) {
mDropTarget = target;
}
return self;
}
#pragma mark touch handling
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self beginDrag];
[self dragAtPosition: [touches anyObject]];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[self dragAtPosition: [touches anyObject]];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[self endDrag];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[self endDrag];
}
#pragma mark dragging logic
- (void) beginDrag
{
mIsDragging = YES;
if ([_delegate respondsToSelector: @selector(droppableViewBeganDragging:)]) {
[_delegate droppableViewBeganDragging: self];
};
mOriginalPosition = self.center;
[self changeSuperView];
}
- (void) dragAtPosition: (UITouch *) touch
{
[UIView beginAnimations: @"drag" context: nil];
self.center = [touch locationInView: self.superview];
[UIView commitAnimations];
if ([_delegate respondsToSelector: @selector(droppableViewDidMove:)]) {
[_delegate droppableViewDidMove:self];
}
if (mDropTarget) {
CGRect intersect = CGRectIntersection(self.frame, mDropTarget.frame);
if (intersect.size.width > 10 || intersect.size.height > 10)
{
if (!mIsOverTarget)
{
mIsOverTarget = YES;
if ([_delegate respondsToSelector: @selector(droppableView:enteredTarget:)]) {
[_delegate droppableView: self enteredTarget: mDropTarget];
}
}
}
else if (mIsOverTarget)
{
mIsOverTarget = NO;
if ([_delegate respondsToSelector: @selector(droppableView:leftTarget:)]) {
[_delegate droppableView: self leftTarget: mDropTarget];
}
}
}
}
- (void) endDrag
{
mIsOverTarget = NO;
if([_delegate respondsToSelector: @selector(droppableViewEndedDragging:)]) {
[_delegate droppableViewEndedDragging: self];
}
if (mDropTarget) {
CGRect intersect = CGRectIntersection(self.frame, mDropTarget.frame);
if (intersect.size.width > 10 || intersect.size.height > 10) {
if([self handleDroppedView]) {
mIsDragging = NO;
return;
}
}
}
[self changeSuperView];
mIsDragging = NO; // this needs to be after superview change
[UIView beginAnimations: @"drag" context: nil];
self.center = mOriginalPosition;
[UIView commitAnimations];
}
- (BOOL) handleDroppedView
{
if (mDropTarget && [_delegate respondsToSelector: @selector(shouldAnimateDroppableViewBack:wasDroppedOnTarget:)]) {
return ![_delegate shouldAnimateDroppableViewBack: self wasDroppedOnTarget: mDropTarget];
}
return NO;
}
#pragma mark superview handling
- (void)willMoveToSuperview:(id)newSuperview
{
if (!mIsDragging && [newSuperview isKindOfClass: [UIScrollView class]]) {
mScrollView = newSuperview;
mOuterView = mScrollView.superview;
}
}
- (void) changeSuperView
{
if (!mScrollView) {
[self.superview bringSubviewToFront: self];
return;
}
UIView * tmp = self.superview;
[self removeFromSuperview];
[mOuterView addSubview: self];
mOuterView = tmp;
// set new position
CGPoint ctr = self.center;
if (mOuterView == mScrollView) {
ctr.x += mScrollView.frame.origin.x - mScrollView.contentOffset.x;
ctr.y += mScrollView.frame.origin.y - mScrollView.contentOffset.y;
} else {
ctr.x -= mScrollView.frame.origin.x - mScrollView.contentOffset.x;
ctr.y -= mScrollView.frame.origin.y - mScrollView.contentOffset.y;
}
self.center = ctr;
}
@end
AppDelegate.h
@interface AppDelegate : UIResponder <UIApplicationDelegate>
{
UIWindow* mWindow;
TestViewController* mViewController;
}
@end
AppDelegate.m
#import "AppDelegate.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
mWindow = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
mWindow.backgroundColor = [UIColor whiteColor];
TestViewController* viewController = [[TestViewController alloc] init];
[mWindow addSubview: viewController.view];
[mWindow makeKeyAndVisible];
return YES;
}
- (void)dealloc
{
[mWindow release];
[mViewController release];
[super dealloc];
}
@结尾
任何帮助深表感谢。
谢谢你。