0

我做了一个小测试,将 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];
}

@结尾

任何帮助深表感谢。

谢谢你。

4

2 回答 2

0

您发布了https://github.com/jaydee3/JDDroppableView/的完整示例代码。

也许您只问一个问题并参考该项目。但是要将它用于 UIImageViews,您需要分配 init 一个 JDDroppableView 并将您的 imageView 放在上面。

UIImageView *imageView = [[UIImageView alloc] initWithImage:...];
imageView.autoresizingMask = UIAutoresizingFlexibleWidth | UIAutoresizingFlexibleHeight;
JDDroppableView *droppableView = [[JDDroppableView alloc] initWithFrame:imageView.bounds];
[droppableView addSubview:imageView];
于 2013-01-11T17:46:35.367 回答
0

根据苹果的文档

新的图像视图对象默认配置为忽略用户事件。如果要在 UIImageView 的自定义子类中处理事件,则必须在初始化对象后将 userInteractionEnabled 属性的值显式更改为 YES。

您需要在 UIImageView 上将 userInteractionEnabled 设置为 YES,如下所示:

[image setUserInteractionEnabled:YES];

希望这有帮助。

于 2012-11-07T11:21:29.437 回答