iPhoneの片手用操作メニュー(QuadCurveMenu編)

iPhoneを片手で扱える操作用メニューを作りたいと思ったのでちょっと調べたことをメモ。

CSS で作るスマートフォン向け片手操作メニュー

これCSSとjQueryなのか、スゲー。
でも、Viewコンテナーとして作りたいんだよなー、と思ったらインスパイア元があるらしい。

ちなみに今回のやつ、デザインは Dribbble に投稿された下記がイケてたのでインスパイアされてみた。

iPhone Search Type Nav (Path Inspired) by Eric Hoffman : Dribbble


エントリーのタイトルにあるように「Path」にインスパイアされてるらしい。
「Path」ってなんぞ?
とググってみたら、ちょっと変わったSNSらしく、その「Path」のiPhoneアプリのUIにインスパイアされてるらしい。

Mobile UI Patterns – CustomNavigation

おぉ、まさにこういうメニューが作りたかったんだよ。

サンプルになりそうなソースが公開されてないか探してみた。
QuadCurveMenu for iOS : Cocoa Controls
levey / QuadCurveMenu : github
ライセンスもMIT Licenseなのでクレジット表記で改変自由。

ARC対応してないソースだったのでARC対応を再度探してみたらあった。
flubbermedia / QuadCurveMenu : github
levey氏のソースからforkしたものだ。

画面左上の配置しか無かったので、6パターンの配置になるようにソースを修正。


左上、左中、左下、右上、右中、右下の順に1~6までの数字ボタンを割り当て、タップすると配置が変更するようにしてみた。
実機で使い心地を試してみたが、親指で操作する場合は中段の配置が一番便利かな。
メニューの展開が180度開く必要があるかは微妙だけど。
邪魔にならない前提を考えると実用的なのはやっぱり下段。
あとはボタンの透明度を上げるとかすれば邪魔な感じが減るかもしれない。

ソースはfork元同様、githubで。
nalabjp / QuadCurveMenu : github

起動中プロセスの状態

Androidにおける起動中のプロセスの状態を知りたい時はRunningAppProcessInfoから知ることができる。
バックグラウンドプロセスをkillする場合等で状態チェックが必要な時に使える。
以下、ソースコード。

package com.nalabjp.example.rapi;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context;
import android.os.Bundle;
import android.widget.ScrollView;
import android.widget.TextView;

public class RunningAppProcessInfoExampleActivity extends Activity {
    
    private ActivityManager manager;
    private ScrollView sc;
    private TextView tv;
    private static Map<Integer, String> importance = new HashMap<Integer, String>();
    private static Map<Integer, String> reason = new HashMap<Integer, String>();
    
    static {
    	importance.put(RunningAppProcessInfo.IMPORTANCE_FOREGROUND, "IMPORTANCE_FOREGROUND");
    	importance.put(RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE, "IMPORTANCE_PERCEPTIBLE");
    	importance.put(RunningAppProcessInfo.IMPORTANCE_VISIBLE, "IMPORTANCE_VISIBLE");
    	importance.put(RunningAppProcessInfo.IMPORTANCE_SERVICE, "IMPORTANCE_SERVICE");
    	importance.put(RunningAppProcessInfo.IMPORTANCE_BACKGROUND, "IMPORTANCE_BACKGROUND");
    	importance.put(RunningAppProcessInfo.IMPORTANCE_EMPTY, "IMPORTANCE_EMPTY");
    	reason.put(RunningAppProcessInfo.REASON_PROVIDER_IN_USE, "REASON_PROVIDER_IN_USE");
    	reason.put(RunningAppProcessInfo.REASON_SERVICE_IN_USE, "REASON_SERVICE_IN_USE");
    	reason.put(RunningAppProcessInfo.REASON_UNKNOWN, "UNKNOWN");
    }
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        manager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
        sc = new ScrollView(this);
        tv  = new TextView(this);
    	sc.addView(tv);
    	setContentView(sc);
    }
    
    @Override
    public void onResume() {
    	super.onResume();
    	searchRunningAppProcesses();
    }
    
    private void searchRunningAppProcesses() {
    	final List<RunningAppProcessInfo> apps = manager.getRunningAppProcesses();
    	StringBuilder sb = new StringBuilder();
    	for (RunningAppProcessInfo rapi : apps) {
    		StringBuilder tmp = new StringBuilder();
    		tmp.append("processName : ").append(rapi.processName).append("\n");
    		tmp.append("importance : ").append(importance.get(rapi.importance)).append("\n");
    		tmp.append("importanceResonCode : ").append(reason.get(rapi.importanceReasonCode)).append("\n");
    		tmp.append("------\n");
    		sb.append(tmp);
    	}
    	tv.setText(sb.toString());
    }
}

結果はこんな感じ。

UITextFieldDelegate

UITextFieldDelegateの動作と戻り値について調べたのでメモ。

(BOOL)textFieldShouldBeginEditing:

  • FirstResponderになる際、一番目に呼ばれるコールバック。
  • YES→FirstResponderになる。
  • NO →FirstResponderにならない。

(void)textFieldDidBeginEditing:

  • FirstResponderになる際、二番目に呼ばれるコールバック。
  • textFieldShouldBeginEditing:でNOが返却された場合は呼ばれない。

(BOOL)textFieldShoultEndEditing:

  • FirstResponderでなくなる際、一番目に呼ばれるコールバック。
  • YES→FirstResponderでなくなる。
  • NO →FirstResponderのまま。

(void)textFieldDidEndEditing:

  • FirstResponderでなくなる際、二番目に呼ばれるコールバック。
  • textFieldShoultEndEditing:でNOが返却された場合は呼ばれない。

(BOOL)textField:shouldChangeCharactersInRange:replacementString:

  • UITextFieldに変更があった際に呼ばれるコールバック。
  • YES→変更が有効になりUITextFieldに反映される。
  • NO →変更は無効になりUITextFieldには反映されない。

(BOOL)textFieldShouldClear:

  • クリアボタンがタップされたときに呼ばれるコールバック。
  • YES→UITextFieldがクリアされる。
  • NO →UITextFieldはクリアされない。

(BOOL)textFieldShouldReturn:

  • リターンキーがタップされた時に呼ばれるコールバック。
  • YES→UITextFieldの「Did End On Exit」イベントが発生する。
  • NO →UITextFieldの「Did End On Exit」イベントは発生しない。

Ricty

Rictyというフォントを使うとコードが見やすくなるというのがTLに流れてきたので入れてみることに。
軽くググってみるとMacPortsかHomebrewを使ってfontforgeを入れるのだとか。
インストール済みだったMacPortsでやってみる。

プログラミング用の見やすいフォント「Ricty」をMacとUbuntuで生成
こちらを参考にインストールしてみると、fontforgeのインストール時にXcodeのCommand Line Toolsが無いと怒られた。
Xcodeが4.3だからなのか、別途インストールしないとダメらしい。
ということで、「Xcode」->「 Open Developer Tool」 ->「 More Developer Tools」からCommand Line Toolsをインストール。
その後にfontforgeのインストールなんだけど、なんかエラー出てるし。
「fatal error: ‘/Developer/Headers/FlatCarbon/Files.h’ file not found」
/Developerなんてないよねってことでココからパッチを取得して、
/opt/local/var/macports/sources/rsync.macports.org/release/tarballs/ports/graphics/fontforge/Portfileに当てる。
これでfontforgeはインストールできた。
あとは特に問題なくRictyを生成しておしまい。

%d人のブロガーが「いいね」をつけました。