1

iPadの音楽アプリには非常に多くの興味深いカスタムUI機能があり、その1つは、特定のアーティストのアルバムを見たときに表示されるテーブルビューです。

各セクションの側面に画像があり、セクションヘッダービューとほぼ同じように機能します。下にスクロールすると、次の画像が表示されるまで一番上の画像が表示されたままになります。その逆も同様です。

layoutSubviews最初は、UITableViewをもう一度再実装しないとまったく不可能に思えますが、UITableViewをサブクラス化して、呼び出し時(つまり、スクロール時)に、uitableviewの外側の側面にこれらのセクション画像を描画するだけで、半ば実行可能だと思います。これにはわずかな問題があります。UITableViewの外側に描画されるため、自動サイズ変更を行うと、レイアウト全体が失われる可能性があります。そして、私はそれのすべての実現可能性について本当に確信が持てません。

何かご意見は?


編集:私の最初のアイデアは、画像側のタッチ自体がテーブルビューによって追跡されないため、そこにタッチしてもスクロールできないという点で機能しないことに気づきました。ここでの最大の問題は、タッチがビュー全体で追跡されるようにタッチを伝播する方法を理解することだと思います。

4

3 に答える 3

1

どういうわけか、テーブルビュー(または最上位など)のどのセクションにいるのかを確認してから、セクションが変更されるたびに更新される UIView を単純に持つことができます。私の考えは説明するのが少し難しいですが、それは関係ありませんUITableView をまったくやり直すと、その機能を埋め込もうとするのではなく、テーブル ビューの横に別のビューを作成して画像を表示するだけです。

これを行う別の方法は、おそらくもう少しトリッキーですが、セルをインデントして、テーブルビューの左端から開始しないようにし、テーブルビューを非常に広くして、それを含むセクションヘッダーにカスタムビューを持たせることができます左側の画像で、うまくいけば正しく動作しますか? 良い質問で、楽しい質問です。

于 2010-08-04T22:28:50.957 に答える
0

さて、私は音楽アプリとスポットライト検索が行うのと同様のことをしました。

UITableViewをサブクラス化しておらず、scrollViewDidScrollメソッドを使用してセクションを追跡し、tableViewの左側にヘッダービューを追加しました(したがって、viewControllerのビューの右側にtableviewを配置する必要があります。つまり、次のことができます。 t UITableViewControllerを使用します)。

このメソッドは、scrollViewDidScroll、ViewDidLoad、およびdidRotateFromInterfaceOrientationで呼び出す必要があります:(回転をサポートしている場合)

左側のスペースは、サポートするインターフェイスの向きのヘッダーのサイズと同じにする必要があることに注意してください。

-(void)updateHeadersLocation
{
for (int sectionNumber = 0; sectionNumber != [self numberOfSectionsInTableView:self.tableView]; sectionNumber++)
{
    // get the rect of the section from the tableview, and convert it to it's superview's coordinates
    CGRect rect = [self.tableView convertRect:[self.tableView rectForSection:sectionNumber] toView:[self.tableView superview]];

    // get the intersection between the section's rect and the view's rect, this will help in knowing what portion of the section is showing
    CGRect intersection = CGRectIntersection(rect, self.tableView.frame);

    CGRect viewFrame = CGRectZero; // we will start off with zero

    viewFrame.size = [self headerSize]; // let's set the size

    viewFrame.origin.x = [self headerXOrigin];

    /*

     three cases:

     1. the section's origin is still showing -> header view will follow the origin
     2. the section's origin isn't showing but some part of the section still shows -> header view will stick to the top
     3. the part of the section that's showing is not sufficient for the view's height -> will move the header view up

     */

    if (rect.origin.y >= self.tableView.frame.origin.y)
    {
        // case 1
        viewFrame.origin.y = rect.origin.y;
    }
    else
    {
        if (intersection.size.height >= viewFrame.size.height)
        {
            // case 2
            viewFrame.origin.y = self.tableView.frame.origin.y;
        }
        else
        {
            // case 3
            viewFrame.origin.y = self.tableView.frame.origin.y + intersection.size.height - viewFrame.size.height;
        }
    }

    UIView* view = [self.headerViewsDictionary objectForKey:[NSString stringWithFormat:@"%i", sectionNumber]];

    // check if the header view is needed
    if (intersection.size.height == 0)
    {
        // not needed, remove it
        if (view)
        {
            [view removeFromSuperview];
            [self.headerViewsDictionary removeObjectForKey:[NSString stringWithFormat:@"%i", sectionNumber]];
            view = nil;
        }
    }
    else if(!view)
    {
        // needed, but not available, create it and add it as a subview

        view = [self headerViewForSection:sectionNumber];

        if (!self.headerViewsDictionary && view)
            self.headerViewsDictionary = [NSMutableDictionary dictionary];

        if (view)
        {
            [self.headerViewsDictionary setValue:view forKey:[NSString stringWithFormat:@"%i", sectionNumber]];

            [self.view addSubview:view];
        }
    }


    [view setFrame:viewFrame];
}
}

また、表示されているビューを保持するプロパティを宣言する必要があります。

@property (nonatomic, strong) NSMutableDictionary* headerViewsDictionary;

これらのメソッドは、ヘッダービューのサイズとX軸オフセットを返します。

-(CGSize)headerSize
{
return CGSizeMake(44.0f, 44.0f);
}

-(CGFloat)headerXOrigin
{
return 10.0f;
} 

不要なヘッダービューが削除されるようにコードを作成したので、必要なときにいつでもビューを返すメソッドが必要です。

-(UIView*)headerViewForSection:(NSInteger)index
{
UIImageView* view = [[UIImageView alloc] init];

if (index % 2)
{
    [view setImage:[UIImage imageNamed:@"call"]];
}
else
{
    [view setImage:[UIImage imageNamed:@"mail"]];
}

return view;
}

これがどのように見えるかです:

セクションのヘッダーは、セクションと同じように画面の外に移動します

セクションのヘッダーはセクションの原点とともに移動しています

lanscapeでどのように表示されるか、tableViewの左側に44pxを与えるために制約を使用しました

横向きで お役に立てれば :)。

于 2012-09-26T14:25:31.033 に答える
0

真夜中にランダムに考えた後、私は最終的に本当の解決策を見つけました.

UITableview を UIScrollView に埋め込み、ユーザーがビューをスクロールすると、タッチはテーブルビュー自体ではなく、親スクロールビューを通過します。必要な作業はほとんどすべて、layoutSubviews メソッドにあります。ユーザーがビューをスクロールするたびに scrollview の layoutSubviews が呼び出されるため、tableview のフレームを変更して画面上で固定し、tableview の contentOffset を scrollview のそれに一致するように変更します。

コード例:

- (void) layoutSubviews{
    tableView.frame = CGRectMake(self.contentOffset.x, self.contentOffset.y, tableView.frame.size.width, tableView.frame.size.height);
    tableView.contentOffset = self.contentOffset;   
}

この時点で、テーブルビューを一方の側に調整し、もう一方の側で必要なことを行うことができます.

于 2010-08-09T16:21:34.420 に答える