ボタンのタップ状態を維持できるようにしたい

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

そんな訳で、『ちょっとしたユーザビリティ向上』についてのメモです。

サンプルプロジェクト:MaintainedButtonSampleをダウンロード

スマホやタブレットといったタッチデバイス向けのアプリでは、タップされた箇所が視覚的に明確となるような仕様をよく見かけたりします。例えば……、

  • タップされたらボタンが光る
  • タップして指を離しても、ボタンが押された状態の外見(ダウンステート)を維持している

と言ったところでしょうか。

ところがAdobe Flexの標準のButtonクラスには、(AIR forでも)この辺の仕様がありません。

PC上でマウスを使って操作する分には、これでもクリックしたということが視覚的に分かるので問題なかったりしますが、タッチパネルとなると、タップする手で画面が隠れてしまい、しっかりとボタンが押されたのかどうかイマイチ分かりにくかったりします。

というわけで、こういった機能を要する場合は、自作する必要があるわけです。

ぶっちゃけToggleButtonを使ってしまえば、話はそこで終わりなんですが、一応作ってみました。地味ですけど。

ソースコード

Buttonクラスを拡張したCustomButton.asを作成します。

package component
{
	import flash.events.MouseEvent;
	import mx.events.FlexEvent;
	import spark.components.Button;

	public class CustomButton extends Button
	{
		/**
		 * Constructor
		 * */
		public function CustomButton()
		{
			super();
		}
		
		//--------------------------------------------------------------------------
		//
		//  Properties
		//
		//--------------------------------------------------------------------------

		//----------------------------------
		//  clicked
		//----------------------------------
		/**
		 *  @private
		 *  Storage for the clicked property 
		 */
		private var _clicked:Boolean;
		
		public function get clicked():Boolean {
			return _clicked;
		}
		
		public function set clicked(value:Boolean):void {
			if (value == _clicked) {
				return;
			}
			_clicked = value;
			dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT));
			invalidateSkinState();
		}

		
		//--------------------------------------------------------------------------
		//
		//  States
		//
		//--------------------------------------------------------------------------
		
		/**
		 *  @private
		 */ 
		override protected function getCurrentSkinState():String {
			if (!clicked) {
				return super.getCurrentSkinState();
			} else {
				return "down";
			}	
		}
		
		/**
		 *  @private
		 */ 
		override protected function buttonReleased():void {
			super.buttonReleased();
			clicked = !clicked;
		}
	}
}

拡張部分は、基本的にToggleButtonクラスのソースコードから部分的に持ってきただけのモノです。

  1. 「clicked」というプロパティを新しく追加する
  2. マウス操作イベントのタイミングで状態を更新するために、setter内で「invalidateSkinState()」を呼び出す
  3. getCurrentSkinState()をオーバーライドし、clickedプロパティがtrueなら「down」ステートを返す
  4. buttonReleased()をオーバーライドし、マウスアップされたタイミングでclickedプロパティの値を更新する

これで、どこのボタンがタップされたのか、もしくはキチンとタップされたのかどうかがハッキリと確認できるようになりました。

補足

ちなみにダウンされた状態を明示的に解除したい場合は、CustomButtonに対して

btnCustom.clicked = false;

という処理を実行してあげればOKです。

このサンプルでは、Viewが遷移して元の画面は破棄されるので、タップされっぱなしの状態でも特に問題ありませんが、例えば遷移の為の条件が足りなくて元の画面に留まりたい場合などは、上記の処理を実行してボタンを元のステートに戻してあげる必要があるわけです。