シームレス」タグアーカイブ

iOSのメモ帳のように表示画面と編集画面をシームレスに切り替える

iOSデバイスのメモ帳は見た目もUIも洗練されていてとてもいいと思います(Android系のメモ帳はあまり使いませんでしたのでよく分かりません。今はかなり洗練されているんでしょうね)。

  • メモの一行目に書いた内容がそのままタイトルとして見えること
  • 起動時は単なるViewerのように見えるのにタッチすると編集モードになってくれ、表示画面と編集画面がシームレス(つぎはぎがない)に切り替えられること

が特長と思います。特に2つ目がいいです。

ios_device_memoapp

ある開発案件に関連して、これをAndroidアプリで実現したいと思いいろいろ調べてみました。

やりたいことは

  • 起動時EditText部品からFocusを外してTextView部品のように見せる
  • タッチ(またはクリック)するとFocusが現れて編集できるようにする
  • 編集を完了する(確認ボタンを押す等)とEditText部品から再度Focusが外れる

です。

調べた結果そのものズバリの質問はありませんでした(もしくは質問はあっても回答がなかった)。

それじゃ自分で解決するしかないと思い海外サイトを含め下記内容のあわせ技で実現させました。

  1. edittext – How to replicate android:editable=”false” in code? – Stack Overflow
  2. たかがフォーカス,されどフォーカス – 愚鈍人
  3. ユーザがTextViewに文字を手入力できるようにしたい。 – Google グループ

解決方法はひとことでいうと、TextView部品ではなくEditText部品を使い、他部品にFocusを退避しておき、必要時にrequestFocusメソッドでFocusを戻す、です。

レイアウトに各部品とその属性(オプション)を設定する

<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:id=”@+id/entire”
android:focusable=”true”
android:focusableInTouchMode=”true”>

<Button android:id=”@+id/confirm”
android:text=”@string/view”/>

<EditText
android:id=”@+id/edit”
android:hint=”@string/hint”
android:inputType=”textMultiLine”
android:scrollbars=”vertical”
android:focusable=”true”
android:focusableInTouchMode=”true”/>

</LinearLayout>

ここでは部品が3つ定義されています。上から背景部品、ボタン部品、EditText部品です。ボタン部品やEditText部品の属性はほぼ省略値そのものですが、背景部品の属性だけ通常と異なります。

ポイントは、背景部品(LinearLayout)に

android:focusable=”true”

を設定します。

背景部品は編集機能を持たずFocusする意味は、通常は、ありません。ここではFocusを退避させられるように故意に設定しています。Focusを退避させられる別部品があればそこに設定しても構いません。ただし編集機能のありそうな(?)部品の場合には困ることがあります。例えばTextView部品があってそこにFocusさせるとEditText部品のような動作になってしまったりします。

JavaプログラムにFocusに関する制御コードを書く

public class AppMain extends Activity {
    private static LinearLayout mBgView;// 背景のLinearLayout部品
    private static EditText mBodyText;// EditText部品

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mBgView = (LinearLayout) findViewById(R.id.entire);
        mBgView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (hasFocus == false) {
                // Focusが来たときに何かさせるならここにコードを
                }else{
                // Focusが外れたときに何かさせるならここにコードを
                }
            }
        });

        mConfirmButton = (Button) findViewById(R.id.confirm);
        mConfirmButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                mBgView.requestFocus();// これでEditTextにあったFocusが外れ、背景部品に移る
            }
        });

        mBgView.requestFocus();// 起動時、背景部品にFocusを退避しておく

    }
}

これで、起動時あたかもTextView部品のように見えていたものが、タッチもしくはクリックするとEditText部品のように編集でき、確認ボタンで再びTextView部品のように見せることができるようになりました。

以上です。