このタイプの展開可能/折りたたみ可能なテーブルビューを作成したいと思います。写真のようにカテゴリとサブカテゴリがあります。たとえば、「健康と美容」はカテゴリであり、下の図のように、開いているサブカテゴリよりもこのセルをクリックすると、では、どうすればこのタイプのテーブルビューを作成できますか?私に提案してください。
15 に答える
最後に、要件がここにあることを正確に説明する2つの非常に便利なヘルプリンクを取得します
。iOS用のTableViewセクションの展開/折りたたみ折りたたみ可能
なテーブルビュー
本当に、そのような種類の拡大/折りたたみテーブルビューセクションのための良い記事
UITableViewに拡張可能なセルには次のコードを使用します
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text=[[self.arForTable objectAtIndex:indexPath.row] valueForKey:@"name"];
[cell setIndentationLevel:[[[self.arForTable objectAtIndex:indexPath.row] valueForKey:@"level"] intValue]];
return cell;
}
行を展開および折りたたむためのコード–TableViewDidSelectRowメソッド
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSDictionary *d=[self.arForTable objectAtIndex:indexPath.row];
if([d valueForKey:@"Objects"]) {
NSArray *ar=[d valueForKey:@"Objects"];
BOOL isAlreadyInserted=NO;
for(NSDictionary *dInner in ar ){
NSInteger index=[self.arForTable indexOfObjectIdenticalTo:dInner];
isAlreadyInserted=(index>0 && index!=NSIntegerMax);
if(isAlreadyInserted) break;
}
if(isAlreadyInserted) {
[self miniMizeThisRows:ar];
} else {
NSUInteger count=indexPath.row+1;
NSMutableArray *arCells=[NSMutableArray array];
for(NSDictionary *dInner in ar ) {
[arCells addObject:[NSIndexPath indexPathForRow:count inSection:0]];
[self.arForTable insertObject:dInner atIndex:count++];
}
[tableView insertRowsAtIndexPaths:arCells withRowAnimation:UITableViewRowAnimationLeft];
}
}
}
行を最小化および最大化/展開-折りたたみするのに役立つメソッド。
-(void)miniMizeThisRows:(NSArray*)ar{
for(NSDictionary *dInner in ar ) {
NSUInteger indexToRemove=[self.arForTable indexOfObjectIdenticalTo:dInner];
NSArray *arInner=[dInner valueForKey:@"Objects"];
if(arInner && [arInner count]>0){
[self miniMizeThisRows:arInner];
}
if([self.arForTable indexOfObjectIdenticalTo:dInner]!=NSNotFound) {
[self.arForTable removeObjectIdenticalTo:dInner];
[self.tableView deleteRowsAtIndexPaths:
[NSArray arrayWithObject:[NSIndexPath indexPathForRow:indexToRemove inSection:0]]
withRowAnimation:UITableViewRowAnimationRight];
}
}
}
ソースコードは私のチュートリアルサイトからダウンロードできます。
これが役立つ場合:[uitableviewの展開可能セクションと折りたたみ可能セクションにアクセス] https://github.com/OliverLetterer/UIExpandableTableView
拡張可能なテーブルビューには少し異なるアプローチがあります。これは、これらの種類のテーブルビューが一般的にどのように構築されるかと一致します。
ヘッダーとセルがあります。ヘッダーはタップ可能である必要があります。そうすると、ヘッダーの下のセルが表示または非表示になります。これは、ジェスチャレコグナイザーをヘッダーに追加することで実現できます。タップすると、そのヘッダーの下にあるすべてのセル(セクション)を削除し、その逆(セルを追加)するだけです。もちろん、どのヘッダーが「開いている」か、どのヘッダーが「閉じている」かという状態を維持する必要があります。
これは、いくつかの理由で便利です。
- ヘッダーとセルの役割が分離されているため、コードがよりクリーンになります。
- このメソッドは、テーブルビューの構築方法(ヘッダーとセル)にうまく対応しているため、それほど魔法はありません。コードはセルを削除または追加するだけであり、iOSの新しいバージョンと互換性があるはずです。
これを実現するために、非常に単純なライブラリを作成しました。テーブルビューがUITableViewセクションのヘッダーとセルで設定されている限り、必要なのはテーブルビューとヘッダーをサブクラス化することだけです。それを試してみてください :)
リンク:https ://github.com/fuzz-productions/FZAccordionTableView
このコードを使用してみてください...これが役立つかもしれません..そして、要件に応じてコードを自由に編集してください...
#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>
@interface ViewController ()
@end
@implementation ViewController
@synthesize myTable;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//myTable.backgroundColor=[UIColor clearColor];
// self.view.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:@"wood.png"]];
muArr= [[NSMutableArray alloc]initWithObjects:@"Vinay",@"Anmol",@"Jagriti", nil];
ExpArr=[[NSMutableArray alloc]initWithObjects:@"Useeee",@"Thissss",@"Codeee", nil];
otherExpand=100;
checker=100;
}
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return muArr.count;
}
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(otherExpand==section)
return ExpArr.count;
return 0;
}
-(BOOL)tableView:(UITableView *)table canCollapse:(NSIndexPath *)indexPath
{
return NO;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *Identifier=@"Cell";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:Identifier];
if (cell==nil)
{
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:Identifier];
}
cell.textLabel.text=[ExpArr objectAtIndex:indexPath.row];
cell.textLabel.backgroundColor=[UIColor clearColor];
UIView *viewww=[[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
viewww.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:@"wood.png"]];
cell.backgroundView=viewww;
// cell.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:@"wood.png"]];
[tableView setSeparatorStyle:UITableViewCellSeparatorStyleSingleLineEtched];
[tableView setSeparatorColor:[UIColor purpleColor]];
return cell;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *view1=[[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 44)];
[view1.layer setCornerRadius:20];
view1.layer.borderWidth=2;
view1.layer.borderColor=[UIColor brownColor].CGColor;
UILabel *label=[[UILabel alloc]initWithFrame:CGRectMake(10, 0, 295, 44)];
label.backgroundColor=[UIColor clearColor];
label.text=[muArr objectAtIndex:section];
UIButton *btn=[UIButton buttonWithType:UIButtonTypeDetailDisclosure];
btn.frame=CGRectMake(280, -5, 50, 50);
btn.backgroundColor=[UIColor clearColor];
btn.tag=section;
view1.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:@"wood.png"]];
label.textColor=[UIColor blackColor];
label.font=[UIFont fontWithName:@"American TypeWriter" size:18];
//btn.backgroundColor=[UIColor blackColor];
[view1 addSubview:btn];
[view1 addSubview:label];
[btn addTarget:self action:@selector(Btntap:) forControlEvents:UIControlEventTouchUpInside];
return view1;
}
-(void)Btntap : (UIButton *)btn
{
if(otherExpand!=100)
{
if (otherExpand==btn.tag)
{
NSMutableArray *tempArr2=[[NSMutableArray alloc]init];
for(int j=0;j<ExpArr.count;j++)
{
NSIndexPath *indexx1=[NSIndexPath indexPathForRow:j inSection:otherExpand];
[tempArr2 addObject:indexx1];
}
checker=0;
otherExpand=100;
[myTable deleteRowsAtIndexPaths:tempArr2 withRowAnimation:UITableViewRowAnimationAutomatic];
}
else
{
NSMutableArray *tempArr2=[[NSMutableArray alloc]init];
for(int j=0;j<ExpArr.count;j++)
{
NSIndexPath *indexx1=[NSIndexPath indexPathForRow:j inSection:otherExpand];
[tempArr2 addObject:indexx1];
}
checker=1;
otherExpand=100;
[myTable deleteRowsAtIndexPaths:tempArr2 withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
if(checker!=0)
{
otherExpand=btn.tag;
//checker=
NSMutableArray *tempArr=[[NSMutableArray alloc]init];
for(int i=0;i<ExpArr.count;i++)
{
NSIndexPath *indexx=[NSIndexPath indexPathForRow:i inSection:btn.tag];
[tempArr addObject:indexx];
}
[myTable insertRowsAtIndexPaths:tempArr withRowAnimation:UITableViewRowAnimationAutomatic];
checker=1;
}
checker=100;
}
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 44;
}
@end
WWDC 2011には、UITableViewの変更、ヒント、コツと呼ばれるすばらしいビデオがあります。このようなことを行う方法を示すセッション125です。サンプルコードTVAnimationsGestures
もチェックしてください
Swiftでこのアコーディオンの例を見ることができます:https ://github.com/tadija/AEAccordion
アコーディオン効果を作成するためのコードはほとんどありません(セクションではなくセルを使用)。ボーナスとして、他のXIBファイル内でXIBファイルを使用するソリューションもあります(カスタムビューを使用するカスタムセルに便利です)。
TLIndexPathToolsは、この種のことを自然に行うことができます。実際、拡張可能なセクションと拡張可能なツリー構造の両方に拡張機能があります。拡張可能なセクションの場合はCollapseサンプルプロジェクトを実行し、拡張可能なツリーの場合はOutlineサンプルプロジェクトを実行してみてください。
TLIndexPathToolsを使用する利点の1つは、シンプルな低レベルAPIとして、一般的なアプローチを使用して、あらゆる種類の動的テーブルビューとコレクションビューの問題を解決できることです。また、CoreDataおよびプレーンアレイと互換的に機能します。
ここで拡張可能なテーブルビューを作成するのはとても簡単です。これは私がこれを行った方法の例です。
これに使用しているデータ
struct ItemList {
var name: String
var items: [String]
var collapsed: Bool
init(name: String, items: [String], collapsed: Bool = false) {
self.name = name
self.items = items
self.collapsed = collapsed
}
}
var sections = [ItemList]()
var items: [ItemList] = [
ItemList(name: "Mac", items: ["MacBook", "MacBook Air"]),
ItemList(name: "iPad", items: ["iPad Pro", "iPad Air 2"]),
ItemList(name: "iPhone", items: ["iPhone 7", "iPhone 6"])
]
ここで、このコードを追加して、それに応じて使用します
extension ViewController:UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 60
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerHeading = UILabel(frame: CGRect(x: 5, y: 10, width: self.view.frame.width, height: 40))
let imageView = UIImageView(frame: CGRect(x: self.view.frame.width - 30, y: 20, width: 20, height: 20))
if items[section].collapsed{
imageView.image = UIImage(named: "collapsed")
}else{
imageView.image = UIImage(named: "expand")
}
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 60))
let tapGuesture = UITapGestureRecognizer(target: self, action: #selector(headerViewTapped))
tapGuesture.numberOfTapsRequired = 1
headerView.addGestureRecognizer(tapGuesture)
headerView.backgroundColor = UIColor.red
headerView.tag = section
headerHeading.text = items[section].name
headerHeading.textColor = .white
headerView.addSubview(headerHeading)
headerView.addSubview(imageView)
return headerView
}
func numberOfSections(in tableView: UITableView) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let itms = items[section]
return !itms.collapsed ? 0 : itms.items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! UITableViewCell
cell.textLabel?.text = items[indexPath.section].items[indexPath.row]
return cell
}
@objc func headerViewTapped(tapped:UITapGestureRecognizer){
print(tapped.view?.tag)
if items[tapped.view!.tag].collapsed == true{
items[tapped.view!.tag].collapsed = false
}else{
items[tapped.view!.tag].collapsed = true
}
if let imView = tapped.view?.subviews[1] as? UIImageView{
if imView.isKind(of: UIImageView.self){
if items[tapped.view!.tag].collapsed{
imView.image = UIImage(named: "collapsed")
}else{
imView.image = UIImage(named: "expand")
}
}
}
tableView.reloadData()
}
}
結果はビンゴです:)
単一のセルをより完全なビューに展開し、それを折りたたんで要約ビューに戻す必要がありました。
だから私がしたことは、を使用してセルを設計することでしたUIStackView
。そして、折りたたんだ状態で表示したくないビューを非表示にして、セルをタップしたときに表示しました。
ここでの秘訣はtableView.beginUpdates()
、tableView.endUpdates()
ステートメント内のビューを表示および非表示にすることです。このようにして、テーブルビューはセルの高さを自動的に調整し、アニメーションで調整します。
セルカスタムクラス:
class AccordionCell: UITableViewCell {
@IBOutlet weak var stackView: UIStackView!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var descriptionLabel: UILabel!
@IBOutlet weak var extendedDescriptionLabel: UILabel!
var expanded: Bool = false {
didSet {
if let extended = self.extendedDescriptionLabel {
extended.isHidden = !expanded
}
}
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.expanded = false
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
UITableViewデリゲートの実装:
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier) as! AccordionCell
cell.titleLabel.text = "Row: \(indexPath.row)"
cell.expanded = indexPath.row == expanded
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? AccordionCell {
tableView.beginUpdates()
if expanded == indexPath.row {
cell.expanded = false
expanded = -1
}
else {
cell.expanded = true
expanded = indexPath.row
}
tableView.endUpdates()
tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? AccordionCell {
tableView.beginUpdates()
cell.expanded = false
tableView.endUpdates()
}
}
}
どのセルが展開されているかを追跡するためにindexpath
、現在展開されているセルの可変保存を導入し、テーブルビューをスクロールしたときに右側のセルが展開されるようにしました。
このリンクを確認してください:
http://iostechnotips.blogspot.in/2014/05/expandable-uitableview.html
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
*UITableView
デリゲートメソッドviewForHeaderInSection
を使用して、カスタムUIViewを返します。
*UIButton
アクション「expandable:(id)sender」を使用してサブビューとして追加し、セクション番号として送信者IDを確認し、テーブルビューを再読み込みします。
.hファイル内
LoadCustomCell *cell1;
NSMutableArray *arrayForBool;
NSMutableArray *questionArray;
NSMutableArray *answerArray;
.mファイル内
viewDidLoadMethod {
_faqTblView.estimatedRowHeight = 30;
_faqTblView.rowHeight = UITableViewAutomaticDimension;
arrayForBool = [[NSMutableArray alloc]init];
_questionArray = [[NSMutableArray alloc]init];
_answerArray = [[NSMutableArray alloc]init];
for (int i = 0; i < _questionArray.count; i++) {
[arrayForBool addObject:@"0"];
}
self.faqTblView.dataSource = self;
self.faqTblView .delegate = self;
[self.faqTblView reloadData];
}
その後
#pragma mark - TableView Datasource & Delegate Method.
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [_questionArray count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
UILabel *lblText = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 260, 100)];
lblText.text = [_questionArray objectAtIndex:section];
return [lblText getLabelHeight] + 20;(created custom class)
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UITapGestureRecognizer *headerTapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(sectionHeaderTapped:)];
cell1 = [[[NSBundle mainBundle] loadNibNamed:@"LoadCustomCell" owner:self options:nil] objectAtIndex:0];
[cell1 setFrame:CGRectMake(0, 0, cell1.frame.size.width, cell1.frame.size.height)];
NSString *numStr = [NSString stringWithFormat:@"%ld. ",section + 1];
[cell1.sideMenuUserNameLabel setText:[numStr stringByAppendingString:[_questionArray objectAtIndex:section]]];
[cell1 setBackgroundColor:[UIColor lightGrayColor]];
cell1.tag = section;
[cell1 addGestureRecognizer:headerTapped];
return cell1;
}
- (void)sectionHeaderTapped:(UITapGestureRecognizer *)gestureRecognizer {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:gestureRecognizer.view.tag];
if (indexPath.row == 0) {
BOOL collapsed = [[arrayForBool objectAtIndex:indexPath.section] boolValue];
for (int i = 0; i < [_questionArray count]; i++) {
if (indexPath.section==i) {
[arrayForBool removeObjectAtIndex:i];
[arrayForBool insertObject:[NSString stringWithFormat:@"%d", !collapsed] atIndex:i];
}
}
NSLog(@"%@", arrayForBool);
[self.faqTblView reloadSections:[NSIndexSet indexSetWithIndex:gestureRecognizer.view.tag] withRowAnimation:UITableViewRowAnimationAutomatic];
for (NSIndexPath *indexPath in self.faqTblView.indexPathsForSelectedRows) {
[self.faqTblView deselectRowAtIndexPath:indexPath animated:NO];
}
cell1.imageView.transform = CGAffineTransformMakeRotation(M_PI);
}
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *questionCellIdentifier = @"questionCellIdentifier";
QuestionCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:questionCellIdentifier];
if (cell == nil) {
NSArray * myNib;
myNib =[[NSBundle mainBundle]loadNibNamed:@"QuestionCustomCell" owner:self options:nil];
cell = (QuestionCustomCell *)[myNib lastObject];
}
BOOL manyCells = [[arrayForBool objectAtIndex:indexPath.section] boolValue];
if(manyCells){
cell.questionNameLbl.text = [_answerArray objectAtIndex:indexPath.section];
}
return cell;
}
ExpyTableViewを使用できます
これにより、指定したセルから拡張可能なセクションが作成されます。iOS8.0まで互換性があります。複数のテーブルビューセルを使用して拡張可能なテーブルビューを生成することにより、柔軟性が得られます。状態の区切り文字を操作するだけで、展開に複数のセルを使用していることがわかりません。
その他の解決策:セルを拡張するために高さを操作します。セルの設計で更新が必要な場合は、コード内のすべての自動レイアウト制約またはロジックを再構築する必要があります。
ExpyTableView:複数のセルを使用し、それらを挿入および削除することで拡張可能なテーブルビューを作成します(これは、拡張と折りたたみを意味します)。将来の設計要求で大きなチャンスがあります。あなたがしなければならないのは、新しいUITableViewCellを追加し、そのためのコードを書くことだけです。あなたは簡単に新しいデザインを手に入れるでしょう。
あなたがしなければならないのはimport ExpyTableView
、それから:
class ViewController: ExpyTableViewDataSource, ExpyTableViewDelegate {
@IBOutlet weak var expandableTableView: ExpyTableView!
// First, set data source and delegate for your table view.
override func viewDidLoad() {
super.viewDidLoad()
expandableTableView.dataSource = self
expandableTableView.delegate = self
}
// Then return your expandable cell instance from expandingCell data source method.
func expandableCell(forSection section: Int, inTableView tableView: ExpyTableView) -> UITableViewCell {
// this cell will be displayed at IndexPath with section: section and row 0
}
}
以前のテーブルビューセクションが拡張可能なテーブルビューセクションになっていることがわかります。サンプルプロジェクトをダウンロードして、より詳細な例を確認することもできます。
折りたたみ可能な(展開および折りたたみ)セルを備えたUITableView迅速5
カスタムセルで非常に使いやすい
消耗品
動的コンテンツ
Githubリンクを確認してください: https ://github.com/Murteza12/ExpandableTablew/wiki/UITableView-with-Collapsible-(expand-and-collapse)-セル