iOS: 在 iCarousel 中对未选择的视图设置约束

3
我正在使用iCarousel来显示我在IB中创建的自定义视图的实例。当旋转木马加载时,旋转木马中的第一个视图正确地显示,如下所示: enter image description here 然而,其他索引似乎忽略了我的约束条件,如下所示: enter image description here 一旦我点击这个视图,布局就会自动调整。同时请注意,第一个索引现在也有了错误的布局: enter image description here 有什么办法可以纠正这个问题吗?我的与旋转木马相关的代码:
- (NSUInteger)numberOfItemsInCarousel:(iCarousel *)carousel
{
    //return the total number of items in the carousel
    NSLog(@"size=%d",audio.count);
    return audio.count;
}

- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view
{
    NSLog(@"get view for index %d",index);
    Audio *aud = [audio objectAtIndex:index];

    CGRect screenRect = [[UIScreen mainScreen] bounds];
    CGFloat screenWidth = screenRect.size.width;
    CGFloat screenHeight = screenRect.size.height;

    AudioView *aView;

    float height = screenWidth*.5;
    float width = height * (16.0/9.0);

    //create new view if no view is available for recycling
    if (view == nil)
    {


        aView = [[[NSBundle mainBundle] loadNibNamed:@"AudioView" owner:self options:nil] objectAtIndex:0];
        [aView setFrame:CGRectMake(0, 0, width, height)];


    }else{
        aView=(AudioView *)view;
    }
    aView.layer.cornerRadius=8;
    NSLog(@"%f",aView.frame.size.height);
    NSLog(@"%f",aView.frame.size.width);


    aView.backgroundColor=[UIColor alizarinColor];
    aView.textLabel.text=aud.text;
    aView.titleLabel.text=aud.name;

    if (rowCurrentlyPlaying==index&&isPlaying) {
        aView.imageView.image = [UIImage imageNamed:@"pause.png"];
    }else{
        aView.imageView.image = [UIImage imageNamed:@"play.png"];
    }



    return aView;
}

- (CGFloat)carousel:(iCarousel *)carousel valueForOption:(iCarouselOption)option withDefault:(CGFloat)value
{
    if (option == iCarouselOptionSpacing)
    {
        return value * 1.1f;
    }
    return value;
}

- (void)carousel:(iCarousel *)carousel didSelectItemAtIndex:(NSInteger)index{
    NSLog(@"Clicked");
    if(index==self.carousel.currentItemIndex){
        Audio *aud = [audio objectAtIndex:index];
        NSURL *audUrl = [NSURL URLWithString:aud.audioUrl];

        if (rowCurrentlyPlaying==index) {
            if (isPlaying) {
                [anAudioStreamer pause];
                isPlaying=NO;
            }else{
                [anAudioStreamer play];
                isPlaying=YES;
            }
        }else{
            rowCurrentlyPlaying=index;
            isPlaying=YES;


            aPlayerItem = [[AVPlayerItem alloc] initWithURL:audUrl];
            anAudioStreamer = [[AVPlayer alloc] initWithPlayerItem:aPlayerItem];
            [anAudioStreamer play];
        }


        [carousel reloadData];

    }

}

编辑:我在iPad上也尝试了这个方法,以下截图可能有助于解决问题(请忽略可笑的字体大小)。从未被选中时,看起来它只是没有完全延伸到整个宽度。

正确布局:enter image description here

不正确的布局:enter image description here


1
嗨詹姆斯,你有找到答案吗?我也遇到了完全相同的问题。 - Josh Gafni
5个回答

4

我整天都在寻找答案,因为我也遇到了同样的问题。设置自定义UIView的框架不起作用。

解决方法有点奇怪:

  1. Go to the xib file for the Custom UIView. I'll also assume that you have corresponding subclass (.h and .m files) for the Custom UIVIew
  2. Add a subview that covers the whole view. I'll call this the background view.
  3. Add the text views, etc as subviews of the background view and set the constraints relative to the background view.
  4. For the background view, add the following constraints: Top Space to Superview, Leading Space to Superview, Width Equals: , Height Equals:
  5. Create two outlets, one from the width constraint and one for the height constraint from step 4. These outlets should be in the .h file of the Custom UIView.
  6. In the viewForItemAtIndex method you have above, continue to allocate and initialize the Custom View using the loadNibNamed method. However, after that, set the width and height constraint constants based on the bounds of the carousel (or whatever width and height you desire). For example,

    CustomView *customView = (CustomView *) view;
    customView.widthConstraint.constant = carousel.bounds.size.width;
    customView.heightConstraint.constant = carousel.bounds.size.height;
    

没有起作用,特别是因为你没有:宽度等于:,高度等于: - Laur Stefan
是的,我有 - 请查看第4个项目的末尾。 - Josh Gafni
1
这个方法完全正常。同时确保您设置了框架和约束。 - Sumit Gera

1
我已经有一段时间没有看iCarousel了,但这是我这里的某个版本中readMe文件中的内容。
iCarousel supports the following built-in display types:

- iCarouselTypeLinear
- iCarouselTypeRotary
- iCarouselTypeInvertedRotary
- iCarouselTypeCylinder
- iCarouselTypeInvertedCylinder
- iCarouselTypeWheel
- iCarouselTypeInvertedWheel
- iCarouselTypeCoverFlow
- iCarouselTypeCoverFlow2
- iCarouselTypeTimeMachine
- iCarouselTypeInvertedTimeMachine

You can also implement your own bespoke carousel styles using `iCarouselTypeCustom` and the `carousel:itemTransformForOffset:baseTransform:` delegate method.

NOTE: The difference between `iCarouselTypeCoverFlow` and `iCarouselTypeCoverFlow2` types is quite subtle, however the logic for `iCarouselTypeCoverFlow2` is substantially more complex. If you flick the carousel they are basically identical, but if you drag the carousel slowly with your finger the difference should be apparent. `iCarouselTypeCoverFlow2` is designed to simulate the standard Apple CoverFlow effect as closely as possible and may change subtly in future in the interests of that goal.

我不确定你是否了解iCarousel正在对那些非当前选择的视图应用变换,这是故意的。它试图模拟苹果的Cover Flow API(我们无法使用)...
好的,所以你的carousel对象有一个名为type的iCarouselType类型属性,从上面的枚举中,最好尝试每个来找到适合你的那个。

谢谢。"linear"走马灯类型运行良好,因此我的问题必须是由于在未选中视图上执行的变换引起的。 - James Harpe

0

对我有帮助的是:

将iCarousel配置(dataSource等)的移动函数移到viewDidAppear函数中。否则,我的框架不正确。

然后只需像这样编写:

currentView?.frame.size.width  = carouselView.bounds.size.width
currentView?.frame.size.height = carouselView.bounds.size.height

希望对某人有所帮助


0

我已经找出了一件看起来不同于iCarousel通常实现的事情。

在方法- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view

我猜你需要使用:objectAtIndex:index];而不是objectAtIndex:0];

if (view == nil)
{
    aView = [[[NSBundle mainBundle] loadNibNamed:@"AudioView" owner:self options:nil] objectAtIndex:0];
    [aView setFrame:CGRectMake(0, 0, width, height)];
}

我有一段简单的代码,我在我的应用程序中使用:

- (UIView *)carousel:(iCarousel *)_carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view
{
if (view == nil)
{
    view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
    view.contentMode = UIViewContentModeCenter;
    [view addSubview:[items objectAtIndex:index]];
}
else
{
    view = [items objectAtIndex:index];
}

view = [items objectAtIndex:index];

return view;
}

希望这有所帮助。

我不理解你的答案。我使用objectAtIndex:0是因为loadNibNamed返回一个NSArray,而我想要其中包含的第一个且唯一的视图。 - James Harpe

0
在“viewForItemAtIndex”中创建音频视图时,只需设置视图的框架即可。
[aView setFrame:CGRectMake(0, 0, width, height)];

我认为您需要设置aView的titlelabel和textlabel的frame,以获得完整宽度的文本。

对于第二个问题,当您单击视图时,该视图会正确显示,但是前一个视图的文本会被截断。

我认为您正在点击时重新加载所有轮播视图,

[carousel reloadData];

而不是这样,您只需重新加载您单击的那个视图即可。为此,您可以使用

  • (void)reloadItemAtIndex:(NSInteger)index animated:(BOOL)animated;

希望这行代码能解决您的问题。

享受吧....


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接