search
LoginSignup
6

More than 5 years have passed since last update.

posted at

updated at

NumberPickerをカスタムして使う

この記事はWHITEPLUS Advent Calendar 2016 7日目になります。

こんにちは。株式会社ホワイトプラス、インターン(エンジニア)の @ksbababa です。

ホワイトプラスではAndroidアプリ開発や技術調査などに関わらせていただいてます。

AndroidでPickerViewのようなもの

iOSではユーザーに選択肢を提示するコントロールにPickerViewがあります。
AndroidではSpinnerを用いることが多いかと思いますが、表示する内容やデザインによってiOSのPickerViewのようなものが欲しいときがあります。

NumberPicker

無いものは作る精神で独自Viewを定義するのもいいですが、AndroidにはiOSのPickerViewに似たNumberPickerというコントロールがあります。
コントロールの名前からは数値専用Pickerのような印象を受けますが、簡単に文字列を表示させることができます。

String[] data = {"hoge", "fuga", "piyo"};
NumberPicker picker = (NumberPicker)findViewById(R.id.SamplePicker);
picker.setDisplayedValues(data);

実行結果

Screen Shot 2016-12-07 at 07.02.27.png

注意点

このままだとsetDisplayedValuesを叩いたり、要素数(maxValue等)の変更をしたりすると落ちてしまうのですが、最初にsetDisplayedValuesにnullを入れておけば解決するはずです。

picker.setDisplayedValues(null);

NumberPickerのStyleを変更する

コードで変更しても良いですが、再利用するならばNumberPickerを継承してクラスを定義するのが楽だと思います。
addView関数をoverrideしてテキストの色を変えてみます。

    @Override
    public void addView(View child, ...) {
        super.addView(child);
        updateView(child);
    }

    private void updateView(View view) {
        if(view instanceof EditText){
            ((EditText) view).setTextColor(Color.RED);
        }
    }

実行結果

Screen Shot 2016-12-07 at 08.04.00.png

データに応じて表示を変える

これだけではあまり面白くないので、データに応じて表示を変えてみます。
例えば、選択肢の一部が選択不可能であることを伝えたい場合を考えます。
選択している値に応じて表示を変えるのでpickerのsetOnValueChangedListenerに以下のような関数を設定します。


    private void setPickerStyles() {
        final int count = picker.getChildCount();
        for (int i = 0; i < count; i++) { // テキスト部を探す
            View child = picker.getChildAt(i);
            if (child instanceof EditText) {
                EditText et = (EditText) child;
                try {
                    Field selectorWheelPaintField = picker.getClass().getSuperclass().getDeclaredField("mSelectorWheelPaint");
                    selectorWheelPaintField.setAccessible(true);
                    Paint pickerPaint = (Paint)selectorWheelPaintField.get(picker);
                    if (et.getText().toString().equals("fuga")) {
                        pickerPaint.setColor(Color.GRAY);  // 選択不可
                    } else {
                        pickerPaint.setColor(Color.BLACK);  // 選択可
                    }
                    picker.invalidate();  // 再描画
                } catch (NoSuchFieldException e) {
                    // 例外処理
                    Log.d("NoSuchFieldException", e.toString());
                } catch (IllegalAccessException e) {
                    // 例外処理
                    Log.d("IllegalAccessException", e.toString());
                }
            }
        }
    }

実行結果

Screen Shot 2016-12-07 at 07.47.05.png

灰色にしただけでdisable感が出たのでは無いでしょうか(?)

まとめ

簡単な内容でしたが、意外と情報が無いような気がしたのでこの機会にまとめてみました。
誰かの助けになれば幸いです。

ホワイトプラスではエンジニアを募集しています

ホワイトプラスでは、新しい技術にどんどん挑戦したい!という技術で事業に貢献したいエンジニアを募集しております。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
6