2014年1月17日金曜日

Androidの色選択ダイアログのデモ


Android SDKには、色を選択するダイアログが無いので、使えそうなものをネットで探していたけど、なかなか用途に合ったものが見つからなかった。というわけで去年、自分で作ってみた。一年かけて少しずつ改良したので、現在のバージョンを公開します。使用はご自由に。

RGBの値をスライダーで細かく制御可能で、モノクロにも対応しています。

http://fumobox.com/file/demo/ColorEditorDemo.zip

ソースをgithubにも置きました。こっちが最新版です。

https://github.com/fumobox/simple_color_chooser_demo

Eclipseのプロジェクトファイルになっています。Android 4.2以上推奨。

使い方は簡単。MainActivityにイベントリスナーを追加して、下のようなコードを呼び出すだけ。
ColorEditDialogFragment.show("Color", _colbox.getColor(), MainActivity.this, MainActivity.this);
主なファイルは以下の3個です。インターフェースの実装方法に問題ありそうだけど、一番シンプルな方法で書いてみました。

MainActivity.java(抜粋)
メインクラス

public class MainActivity extends Activity implements ColorEditDialogFragment.OnColorChangedListener{

 private ColorBoxView _colbox;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  _colbox = (ColorBoxView) findViewById(R.id.colbox);
  
  Button bt = (Button) findViewById(R.id.button1);
  bt.setOnClickListener(new android.view.View.OnClickListener() {
   @Override
   public void onClick(View v) {
    ColorEditDialogFragment.show("Color", _colbox.getColor(), MainActivity.this, MainActivity.this);
   }
  });
 }

 @Override
 public void colorChanged(int color, int r, int g, int b) {
  _colbox.setColor(color);
 }

}

ColorEditDialogFragment.java(抜粋)
メインダイアログ

public class ColorEditDialogFragment extends DialogFragment {

 private OnColorChangedListener _listener;
 
 public static void show(String title, int color, OnColorChangedListener listener, Activity act) {
  ColorEditDialogFragment d = new ColorEditDialogFragment();
  d._listener = listener;
  Bundle args = new Bundle();
  args.putString("title", title);
  args.putInt("color", color);
  d.setArguments(args);
  d.show(act.getFragmentManager(), "dialog");
 }
 
 public interface OnColorChangedListener {
  void colorChanged(int color, int r, int g, int b);
 }
 
 @Override
 public Dialog onCreateDialog(Bundle savedInstanceState) {
  ColorEditDialog d = new ColorEditDialog(this.getActivity());
  return d;
 }
 
 private class ColorEditDialog extends Dialog {

  private int _color;
  private int _r, _g, _b;
  
  private CheckBox _cb_mono;

  private TextView _tv01;

  private ColorBoxView _colbox;

  private SeekBar[] _sb;

  public ColorEditDialog(Context context) {
   super(context);
  }

  public void onCreate(Bundle savedInstanceState) {
   setCanceledOnTouchOutside(true);
   setContentView(this.getLayoutInflater().inflate(R.layout.color_edit, null));
   
   String title = getArguments().getString("title");
   this.setTitle(title);
   
   _color = getArguments().getInt("color");
   
   _colbox = (ColorBoxView) findViewById(R.id.colbox);
   _sb = new SeekBar[3];
   _sb[0] = (SeekBar) findViewById(R.id.sb_gap);
   _sb[0].setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
     if (!fromUser) {
      return;
     }
     _r = progress;
     if (_cb_mono.isChecked()) {
      _sb[1].setProgress(progress);
      _sb[2].setProgress(progress);
      _g = progress;
      _b = progress;
     }
     combineColor();
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
    }
   });

   _sb[1] = (SeekBar) findViewById(R.id.sb_g);
   _sb[1].setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
     if (!fromUser) {
      return;
     }
     _g = progress;
     if (_cb_mono.isChecked()) {
      _sb[0].setProgress(progress);
      _sb[2].setProgress(progress);
      _r = progress;
      _b = progress;
     }
     combineColor();
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
    }
   });

   _sb[2] = (SeekBar) findViewById(R.id.sb_b);
   _sb[2].setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
     if (!fromUser) {
      return;
     }
     _b = progress;
     if (_cb_mono.isChecked()) {
      _sb[0].setProgress(progress);
      _sb[1].setProgress(progress);
      _r = progress;
      _g = progress;
     }
     combineColor();
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
    }
   });

   _tv01 = (TextView) findViewById(R.id.tv01);

   _cb_mono = (CheckBox) findViewById(R.id.cb_marge);
   _cb_mono.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View arg0) {
     if (_cb_mono.isChecked()) {
      _r = _sb[0].getProgress();
      _sb[1].setProgress(_r);
      _sb[2].setProgress(_r);
      _g = _r;
      _b = _r;
      combineColor();
     } else {

     }
    }
   });

   Button bt_ok = (Button) findViewById(R.id.bt_ok);
   bt_ok.setOnClickListener(new android.view.View.OnClickListener() {
    @Override
    public void onClick(View v) {
     ColorEditDialog.this.dismiss();
     if (_listener != null) {
      _listener.colorChanged(_color, _r, _g, _b);
     }
    }
   });

   Button bt_cancel = (Button) findViewById(R.id.bt_cancel);
   bt_cancel.setOnClickListener(new android.view.View.OnClickListener() {
    @Override
    public void onClick(View v) {
     dismiss();
    }
   });
   
   adjustBar();
  }

  public void adjustBar() {
   _r = (_color >>> 16) & 0xff;
   _g = (_color >>> 8) & 0xff;
   _b = (_color >>> 0) & 0xff;
   _sb[0].setProgress(_r);
   _sb[1].setProgress(_g);
   _sb[2].setProgress(_b);
   _colbox.setColor(_color);
   _tv01.setText("#" + Integer.toHexString(_color & 0x00ffffff) + " (" + _r + ", " + _g + ", " + _b + ")");
  }

  public void combineColor() {
   _color = 0xff000000;
   _color |= _r << 16;
   _color |= _g << 8;
   _color |= _b;
   _colbox.setColor(_color);
   _tv01.setText("#" + Integer.toHexString(_color & 0x00ffffff) + " (" + _r + ", " + _g + ", " + _b + ")");
  }

 }
 
}

ColorEditDialogFragment.java(抜粋)
色の表示用ボックス
public class ColorBoxView extends SurfaceView implements SurfaceHolder.Callback {

 private SurfaceHolder _sh;
 
 public static final int PADDING_DEFAULT = 4;
 private int _padding = PADDING_DEFAULT;

 public static final int COLOR_DEFAULT = 0xffffffff;
 private int _color = COLOR_DEFAULT; 
 
 public ColorBoxView(Context context) {
  super(context);
  init();
 }

 public ColorBoxView(Context context, AttributeSet attrs) {
  super(context, attrs);
  init();
 }

 public ColorBoxView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  init();
 }
 
 private void init() {
  _sh = getHolder();
  _sh.addCallback(this);
  _sh.setFormat(PixelFormat.TRANSLUCENT);
  
  setFocusable(true);
  setZOrderOnTop(true);
 }
 
 @Override
 public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
 }

 @Override
 public void surfaceCreated(SurfaceHolder arg0) {
  draw();
 }

 @Override
 public void surfaceDestroyed(SurfaceHolder arg0) {
 }
 
 public void draw() {
  Canvas canvas = _sh.lockCanvas();
  if(canvas == null) {
   return;
  }
  
  float w = this.getWidth();
  float h = this.getHeight();
  float bw = w - _padding * 2f;
  float bh = h - _padding * 2f;
  RectF rect = new RectF(_padding, _padding, _padding + bw, _padding + bh);
  
  Paint p = new Paint();
  p.setAntiAlias(true);
  
  canvas.drawColor(Color.TRANSPARENT, android.graphics.PorterDuff.Mode.CLEAR);

  p.setStyle(Style.FILL);
  p.setColor(_color);
  canvas.drawRoundRect(rect, 4, 4, p);

  p.setStyle(Style.STROKE);
  p.setStrokeWidth(2);
  p.setColor(0xff666666);
  canvas.drawRoundRect(rect, 4, 4, p);
  
  _sh.unlockCanvasAndPost(canvas);
 }
 
 @Override
 public boolean onTouchEvent(MotionEvent e) {
  return true;
 }
 
 public int getColor() {
  return _color;
 }
 
 public void setColor(int color) {
  _color = color | 0xff000000;
  draw();
 }
 
}

1/18 追記

ソースをgithubにも置きました。こっちが最新版です。

https://github.com/fumobox/simple_color_chooser_demo

0 件のコメント:

コメントを投稿