TextViewの一部の文字色を変更する

TextViewの文字列にHTMLタグが使えるのを知らなかったのでメモ。

今日も仕事で半分徹夜。そろそろ…

このように、文の一部分だけを赤色にしたいとする。ぱっと見全然難しいプログラムではなさそうだけど、実際にTextViewで実現しようとしたらちょっと迷った。

一番始めに思いついたのは、同色の文字毎にTextViewを作り横に並べれるという方法。1行に収まるならこれで良さそうだけど、複数行になる場合、自然な改行処理をするのがすごい面倒臭そうということで断念。 じゃあ、独自Viewを作ってdrawメソッド内にテキスト描画処理を組み込むか、と考えたけどこちらもむろんTextViewを使うだけの場合より相当面倒くさい。

こんな時に便利なのが、android.text.HtmlのfromHtmlメソッド。

HTMLタグを使えるので、以下のようにHTML文書を作成する感覚で手軽に文字修飾が出来てしまう。

textView.setText(Html.fromHtml(“今日も仕事で<font color=\”red\”> 半分徹夜</font>そろそろ…”));

さらに感動したのはbタグも使える事。 Androidの場合、機種によってはTextViewの日本語BOLD修飾が対応していない。 こういったケースの場合、いつもは苦肉の策としてPaintを使って文字淵を描いたり、TextViewのシャドウ機能を使って影を重ねて文字を太く見せたりしたけどHtml.fromHtmlを使えば、単純にbタグを使えばOKのよう。

これは非常に便利だ。 HTML5の時代にfontタグで文字修飾をするなんて相当なルール違反だろうけど、、まあ、TextViewはHTML文書ではないからいいよね?



buttonタグがsubmitするのを無効に

formの中にbuttonタグを設置すると、button押下でformがsubmitされてしまう。

例えば、こんな状態

<form>
・・・・・
<button>ID重複チェック</button>
・・・・・
<input type="submit" value="送信">
</form>

buttonはAJAXの操作等に割り当て、form送信は普通にsubmitで実行したい、、こんなとき、非常に便利な属性があった。
buttonにtype属性で「button」を指定する。

<button type="button">ID重複チェック</button>

こうすることでbuttonがformのsubmitとして機能しなくなる。
地味だけど、非常に便利。こんな属性しらなかった。



php POST送信時の「Content-type not specified assuming application/x-www-form-urlencoded」エラー

phpでフォームを使わずに直接POST送信したら
「Content-type not specified assuming application/x-www-form-urlencoded」
というエラーが出たのでコードを修正した際のメモ。

これはデータ送信する際のheaderが足りない!という内容のエラーらしい。エラー前は↓のような感じでメソッドタイプとデータを渡してPOSTした。

$data =array(
	'param1' => $param1,
	'param2' => $param2
);
					
$data = http_build_query($data, "", "&");
					
$options =array(
	'http' =>array(
			'method' => 'POST',
			'content' => $data
		)
	);

$contents =file_get_contents($url, false, stream_context_create($options));

修正後は、$optionsの配列にヘッダーを設定。こうすることでエラーが無くなり無事送信完了。

$data =array(
	'param1' => $param1,
	'param2' => $param2
);
					
$data = http_build_query($data, "", "&");

$header = array(
		"Content-Type: application/x-www-form-urlencoded",
		"Content-Length: ".strlen($data)
	);
					
$options =array(
	'http' =>array(
			'method' => 'POST',
			'header' => implode("\r\n", $header),
			'content' => $data
		)
	);

$contents =file_get_contents($url, false, stream_context_create($options));



TextViewのフォーカスを有効にする

androidのTextViewでフォーカスを有効にしようと思ったけど、うまく行かなかったのでメモ。

xmlで普通に↓「focusable」をtrueにすればいいだけかと思っていたらうまく行かなかった。

<TextView
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="てきすと"
  android:focusable="true"
  />

↓のように「focusable」と「focusableInTouchMode」をtrueにするとうまく行った。

<TextView
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="てきすと"
  android:focusable="true"
  android:focusableInTouchMode="true"
  />

「focusableInTouchMode」はTouchモード時にViewがフォーカスを取得可能か設定するオプションとのこと。



MySQLで日付毎の集計を計算する

 データベースを使って集計表見たいなものを作っていると、日付毎の合計数などが知りたい場合がある。
普通にレコードに記録した日付でグループ化して合計とれば良い、というのはわかるけど
日付の型をDATETIMEにしていると時、分、秒も要素として入ってしまうので同じ日付でも1秒違うと違う
グループになってしまう。まあ、当たり前だ。

では、これをシンプルにまとめるコードが無いかと思い調べたのでメモ。
例えば

id | ip | update_time
——————————————–
1 | 192.168.0.1 | 2012-06-29 11:11:11
——————————————–
2 | 192.168.0.2 | 2012-06-29 11:11:12
——————————————–
3 | 192.168.0.1 | 2012-06-29 11:11:13

見たいなテーブルがあったとしたら、
substringを使って日付部分の文字を切り出し、その結果をselect文に入れてグループ化する。
具体的には以下のような感じ。

select substring(update_time,1,10) as date,count(id) as cut
 from tbl group by date

 MySQLを使いました。



Objective-Cでクラス変数を定義

 Objective-Cにはクラス変数を定義する仕組みが無いようだ。
 同様の変数を使いたい場合は、static指定子を使って変数宣言するみたい。

@interface Greeting : NSObject
+(void)setMessage:(char *)message;
-(void)say;
@end

static char *msg ="good morning!!";


@implementation Greeting
+(void)setMessage:(char *)message{
	msg = message;
}
-(void)say{
	printf("%s\n", msg);	
}
@end


int main(void){
	id obj = [[Greeting alloc] init];
	[obj say];	// good morning!と表示
	
	// クラス変数を書き換え
	[Greeting setMessage:"hello!"];
	[obj say];	// hello!と表示
	
	return 0;
}

定義ファイルで利用できる局所変数を作るというノリらしい。
しかし、Objective-Cは難しい。なかなか覚えられない。



ファイルアップロードクラスで任意のフィールドのアップロード状態をチェックする

 CodeIgniterを使ったフレームワークで、複数のファイルアップロードフィールドを作った場合、アップロード実行メソッドを「$this->upload->do_upload()」としてしまうと全てのフィールドがチェック対象になってしまう。

 ファイル参照があったフィールドだけアップロードチェックを行いたい場合はどうしたら良いか。

 調べたらdo_uploadメソッドの引数にフィールド名を入れれば良いだけだった。

 とっても簡単。

$config["upload_path"] = "./image/";
$config["allowed_types"] ="gif|jpg|png";
$config["max_size"] ="100";
$config["max_width"] ="1024";
$config["max_height"] ="768";
		
$this->upload->initialize($config);
if(!$this->upload->do_upload("フォームの対象フィールド名"))
{
	// エラー処理
}
else
{
	// 成功!
}

アップロードフィールドが沢山ある場合はフィールド名を値とした配列を使ってforeachでブンブンまわし、オリジナルのチェック関数を通してチェック処理を行えば管理がスムーズになる。

フィールドに値がセットされているかどうかは、スーパーグローバル変数「$_FILES」を使って判断すればok。

$fields = array("file_up1", "file_up2", "file_up3");
foreach($fields as $field)
{
	// _upload_check_fncはフィールド名を引数に渡すと、
	// 上記のファイルアップロード処理を実行するオリジナル関数
	$this->_upload_check_fnc($field);
}

ところで、このCodeIgniterのファイルアップロードクラス、アップロードしたファイル名を任意に決めるような機能がなさそうなんだけど、やっぱ無いんだろうか。

仕方ないので同じファイル名があった場合は、連番をつける設定にしてファイルをアップロードし、サーバーにファイルをアップロード後、任意の名前にリネームした。なんかスマートでないけど好きなファイル名にする場合はこんな感じにするしかない?