2012/12/22

ScrollView を使わないで TextView に スクロールバーを表示する

Android の ScrollView、便利なのですが、内容にあわせて高さを変更したい場合などには向いていません。

特に、TextView の最大高を行数で指定したい場合、ScrollView を使用することが出来ません。
まぁ絶対使えないのかと言われると不可能ではないと思いますが、かなり面倒くさいことになると思います。

では、簡単に出来る方法は無いのかというと、View には Scrollbar を表示する機能がデフォルトでついているので、これを利用することが出来ます。
参考:Android TextView with scrollbars and maxHeight - Stack Overflow

まず、生成する TextView を以下のように定義します。
<TextView
    android:id="@+id/text_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:singleLine="false"
    android:maxLines="3"  // ←ポイント
    android:scrollbars="vertical" />

上記のように maxLines を指定しておくと、使用しているフォントサイズにあわせて TextView の高さを自動調整してくれます。

さて、このままでスクロールしてくれれば本当に簡単なのですが、残念ながらそこまで簡単ではありません。
以下のコードを Java 側に記述しておく必要があります。
(大抵の場合は Activity.onCreate に書いておけばよいでしょう。)
TextView textView = (TextView)findViewById(R.id.text_view);
textView.setMovementMethod(ScrollingMovementMethod.getInstance());

これで TextView の中身がスクロールするようになります。

ちなみに、参考にしたサイトには、以下の記述があります。
android:textColor="@android:color/secondary_text_dark_nodisable"
これは、Android 2.3 以前では、TextView をクリックした時に文字色が反転してしまうため、文字色を灰色にすることで、その問題を防ぐという意味があります。
しかし、これを書いてしまうと TextView の文字色が灰色になってしまうので、ベストな方法とは言い難いです。

この問題は、 android.Theme.Dark の場合にのみ起こるようなので、android:Theme.Light 等を Application や Activity の theme として設定すれば回避することが出来ます。
もちろん、全体のテーマから変更されるので、全体的に白を基調としたデザインに変更されてしまいますが、Google としては白基調を推奨しているようなので、なるべくなら白基調でうまく作っていくのが良いでしょう。


注:
今回の方法では指に追従するスクロールになってしまいます。
フリックで自動スクロールするようにするためには、 ScrollingMovementMethod を継承した独自の MovementMethod を作成する必要があります。

2 件のコメント:

匿名 さんのコメント...

参考にさせて頂いてTextviewのスクロールには成功しました。
しかし、自分の場合定義ファイルを使わないためにXMLのandroid:scrollbars="vertical"ではなくコード側でsetVerticalScrollBarEnabled(true); を実行しているのですがスクロールバーが表示されません。
コードベースでは無理なんでしょうか…。

Yusuke Miura さんのコメント...

確認してみましたが、確かにコードベースではスクロールバーが表示されませんね。
TextView インスタンスの生成時に Attribute が渡されていないのが原因ではないかと推察しますが、ちゃんとした原因はもう少し調べないとわからないです。

理論上はコードベースでも同じ動作をさせることは可能なはずです。
XML で書いた場合も、LayoutInflater が 各View を生成しているわけですので。
ただ、LayoutInflater は結構複雑な仕事をこなしているので、全く同じことをさせようとするとかなり大変だと思います。