忍者ブログ

Home > > IB不使用&オープンソースなiPadアプリ(テキストエディタ)を作る 第6回:AccessoryView、カーソル移動

[PR]

  • 2024-04-20

Share on Tumblr このエントリーをはてなブックマークに追加

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

Comments:

Trackback+Pingback:

Listed below are links to weblogs that reference
[PR] from Born Neet

Home > > IB不使用&オープンソースなiPadアプリ(テキストエディタ)を作る 第6回:AccessoryView、カーソル移動

Home > Edhita > IB不使用&オープンソースなiPadアプリ(テキストエディタ)を作る 第6回:AccessoryView、カーソル移動

IB不使用&オープンソースなiPadアプリ(テキストエディタ)を作る 第6回:AccessoryView、カーソル移動

Share on Tumblr このエントリーをはてなブックマークに追加

第6回です。
奇跡的にまだ飽きてません。
この勢いで電子書籍を出せるまで頑張りたいと思います。

今回はキーボードの上部にAccessoryViewを表示させて、
そこから記号やタブを入力できるようにします。

また、ついでにツールバーのボタンからカーソルを左右に移動できるようにします。

参考

今回も参考書籍(第1回参照)とAppleのドキュメントのみです。

素材

引き続き、Soft * Accessory様の素材をお借りしています。

1. AccessoryViewの作成

まず、AccessoryViewを作成します。

と言っても、UIViewを継承したEdhitaAccessoryViewを作成し、
その上に記号入力用のUIButtonを配置するだけ。

特別なことは必要ありません。

// EdhitaAccessoryView.m

- (id)initWithTextView:(UITextView *)textView {
	if (self = [super init]) {
		
		textView_ = textView;

		NSInteger padding = 8;
		NSInteger margin = 8;
		NSInteger size = 46;
		
		self.frame = CGRectMake(0, 0, 768, size + padding * 2);
		self.backgroundColor = [UIColor lightGrayColor];
		
		// あんまりボタンを表示すると小さくせざるをえないので、使用頻度が高そうで入力しづらいやつを
		NSArray *titles = [NSArray arrayWithObjects: @"{", @"}" ,@"<", @">", @"[", @"]", @"+", @"*", @"=", @"_", @"#", @"|", @"\\", nil];		
		
		UIButton *button;
		
		// 記号
		NSInteger i = 0;
		for (NSString *title in titles) {

			button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
			button.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
			button.frame = CGRectMake((size + margin) * i + padding, padding, size, size);
			[button setTitle:title forState:UIControlStateNormal];
			[button addTarget:self action:@selector(insertDidPush:) forControlEvents:UIControlEventTouchUpInside];
			button.titleLabel.font = [UIFont systemFontOfSize: 20];
			[self addSubview:button];
			i++;
		}

		// タブ
		button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
		button.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
		button.frame = CGRectMake(self.frame.size.width - size - padding, padding, size, size);
		[button setTitle:@"\\t" forState:UIControlStateNormal];
		[button addTarget:self action:@selector(tabDidPush) forControlEvents:UIControlEventTouchUpInside];
		[self addSubview:button];

	}
	return self;
}

2. AccessoryViewの表示

先程作ったViewをTextViewのAccessoryViewとして設定します。

方法は、DetailViewControllerのinit内で、
textView_のinputAccessoryViewにインスタンスを代入するだけ。

これでAccessoryViewが表示されるようになります。
簡単ですね!

		if ([settings objectForKey:@"accessoryView"] == NULL || [settings boolForKey:@"accessoryView"]) {
			EdhitaAccessoryView *accessoryView = [[EdhitaAccessoryView alloc] initWithTextView:textView_];
			textView_.inputAccessoryView = accessoryView;
		}

人によってはAccessoryViewが邪魔だという人もいると思うので、
Settingsに項目を追加してON/OFFできるようにしています。
上のif文はONに設定されているか(デフォルトON)を判別しています。

		<dict>
			<key>Type</key>
			<string>PSGroupSpecifier</string>
			<key>Title</key>
			<string>Input</string>
		</dict>
		<dict>
			<key>Type</key>
			<string>PSToggleSwitchSpecifier</string>
			<key>Title</key>
			<string>Accessory View</string>
			<key>Key</key>
			<string>accessoryView</string>
			<key>DefaultValue</key>
			<true/>
		</dict>

3. 記号入力処理

AccessoryViewのボタンから記号を入力できるようにします。

やることは簡単で、ボタンがタップされたら、TextViewのselectedRangeを取得して、
ボタンのtitleLabel.text(タブの場合は\t)で置換します。
また、undoできるようにundoManagerに反対の処理(backspace)を仕込んでいます。
※ 見ての通り、view内に処理をがっつり書いちゃってます。
 MVC的にアウトだと思うんですが、
 この為に新たにControllerを作るのもどうかと思うし、
 これ以上DetailControllerを肥大化させてくないし…ということで一旦こういう実装にしています。
 今後勉強していく中で綺麗なアーキテクチャがわかったら直します。

// EdhitaAccessoryView.m

- (void)insertDidPush:(UIButton *)button {
	[self insertString:button.titleLabel.text];
}

- (void)tabDidPush {
	[self insertString:@"\t"];
}

- (void)insertString:(NSString *)string {

	NSMutableString *text = [textView_.text mutableCopy];

	NSRange range = textView_.selectedRange;
	[text replaceCharactersInRange:range withString:string];

	// カーソルが最後に行っちゃうので選択しなおす
	textView_.text = text;
	textView_.selectedRange = NSMakeRange(range.location + 1, range.length);

	// undo登録
	[[textView_ undoManager] registerUndoWithTarget:self selector:@selector(backSpace:) object:string];
}

- (void)backSpace:(NSString *)string {
	
	NSMutableString *text = [textView_.text mutableCopy];

	// 手前にカーソルを戻して空文字で1文字分置換
	NSRange range = textView_.selectedRange;
	textView_.selectedRange = NSMakeRange(range.location - 1, 1);
	[text replaceCharactersInRange:textView_.selectedRange withString:@""];
	textView_.text = text;
	
	textView_.selectedRange = NSMakeRange(range.location - 1, 0);

	// redo登録
	[[textView_ undoManager] registerUndoWithTarget:self selector:@selector(insertString:) object:string];
}

4. カーソル移動

最後にカーソルキーによるキャレットの移動です。

本当はAccessoryViewのボタンでやりたかったんですが、
どうしてもPortraitの時に幅が足りなくなるので、
ツールバーでやってます。

処理としては、selectedRangeのlocationを±1して設定しなおしているだけです。
上下移動は文字数とか考慮しなきゃいけないので保留です。

- (void)leftDidPush {
	NSRange range = textView_.selectedRange;
	textView_.selectedRange = NSMakeRange(range.location - 1, range.length);
	[[textView_ undoManager] registerUndoWithTarget:self selector:@selector(rightDidPush) object:nil];
}

- (void)rightDidPush {
	NSRange range = textView_.selectedRange;
	textView_.selectedRange = NSMakeRange(range.location + 1, range.length);
	[[textView_ undoManager] registerUndoWithTarget:self selector:@selector(leftDidPush) object:nil];
}

[完成]

できました!
AccessoryViewの実装

[まとめ]

いかがだったでしょうか。

だいぶTextEditorらしくなってきましたが、
肝心のSyntax Highlightingが後回しのまま…。

まだ検討もついてませんが、
そろそろやるしかないですねぇ。

[コード]

今回のコードは「Edhita6.zip」に入っています。
GitHubのdownloadページからダウンロードして下さい。

Downloads for tnantoka's Edhita - GitHub

PR

Comments:0

Comment Form

Trackback+Pingback:

TrackBack URL for this entry
Listed below are links to weblogs that reference
IB不使用&オープンソースなiPadアプリ(テキストエディタ)を作る 第6回:AccessoryView、カーソル移動 from Born Neet

Home > Edhita > IB不使用&オープンソースなiPadアプリ(テキストエディタ)を作る 第6回:AccessoryView、カーソル移動

Search
Loading
Feeds
Links
スポンサードリンク

Page Top