@Override
 public void afterTextChanged(Editable s) {
   if (ignoreChanges) return;
   final View f = getFocusedChild();
   if (f == txtH || f == txtS || f == txtV) {
     int nh, ns, nv;
     try {
       nh = Integer.parseInt(txtH.getText().toString());
       if (nh > 360 || nh < 0) return;
       ns = Integer.parseInt(txtS.getText().toString());
       if (ns > 100 || ns < 0) return;
       nv = Integer.parseInt(txtV.getText().toString());
       if (nv > 100 || nv < 0) return;
       hsv.h = (double) nh / 360.0;
       hsv.s = (double) ns / 100.0;
       hsv.v = (double) nv / 100.0;
     } catch (Throwable ex) {
       return;
     }
     ignoreChanges = true;
     currentColor = hsv.toRGB(false);
     barH.setValue(nh);
     barS.setValue(ns);
     barV.setValue(nv);
     txt.setText(ColorUtils.toHexColor(currentColor));
     ignoreChanges = false;
   } else {
     String cs = s.toString().trim();
     if (cs.length() < 6) return;
     if (cs.charAt(0) == '#') cs = cs.substring(1).trim();
     if (cs.length() != 6) return;
     int c = ColorUtils.parseHexColor(cs);
     if (c == 0) return;
     currentColor = c;
     hsv.fromRGB(c);
     ignoreChanges = true;
     c = (int) (hsv.h * 360.0);
     barH.setValue(c);
     txtH.setText(Integer.toString(c));
     c = (int) (hsv.s * 100.0);
     barS.setValue(c);
     txtS.setText(Integer.toString(c));
     c = (int) (hsv.v * 100.0);
     barV.setValue(c);
     txtV.setText(Integer.toString(c));
     ignoreChanges = false;
   }
   updateGH();
   updateGS();
   updateGV();
   barH.invalidate();
   barS.invalidate();
   barV.invalidate();
   bgCurrent.setColor(currentColor);
   lblCurrent.invalidate();
 }
 @Override
 public void onValueChanged(BgSeekBar seekBar, int value, boolean fromUser, boolean usingKeys) {
   if (ignoreChanges) return;
   hsv.h = barH.getValue() / 360.0;
   hsv.s = barS.getValue() / 100.0;
   hsv.v = barV.getValue() / 100.0;
   currentColor = hsv.toRGB(false);
   if (seekBar == barH) {
     updateGS();
     updateGV();
   } else if (seekBar == barS) {
     updateGH();
     updateGV();
   } else if (seekBar == barV) {
     updateGH();
     updateGS();
   }
   ignoreChanges = true;
   txtH.setText(Integer.toString((int) (hsv.h * 360.0)));
   txtS.setText(Integer.toString((int) (hsv.s * 100.0)));
   txtV.setText(Integer.toString((int) (hsv.v * 100.0)));
   txt.setText(ColorUtils.toHexColor(currentColor));
   ignoreChanges = false;
   barH.invalidate();
   barS.invalidate();
   barV.invalidate();
   bgCurrent.setColor(currentColor);
   lblCurrent.invalidate();
 }
 private void updateGV() {
   final int h = barV.getHeight();
   bmpV = updateBitmap(bmpV, h);
   bmpBuf = updateBuffer(bmpBuf, h);
   hsvTmp.h = hsv.h;
   hsvTmp.s = hsv.s;
   final double d = (double) (h - 1);
   for (int i = 0; i < h; i++) {
     hsvTmp.v = (double) i / d;
     bmpBuf.put(i, hsvTmp.toRGB(true));
   }
   bmpV.copyPixelsFromBuffer(bmpBuf);
 }
  @SuppressWarnings("deprecation")
  private void init(Context context, int initialColor) {
    setPadding(UI.dialogMargin, UI.dialogMargin, UI.dialogMargin, UI.dialogMargin);
    final int eachW = (UI._18sp * 7) >> 1;
    final boolean smallScreen = (UI.isLowDpiScreen && !UI.isLargeScreen);
    initialColor = 0xff000000 | (initialColor & 0x00ffffff);
    hsv = new HSV();
    hsv.fromRGB(initialColor);
    hsvTmp = new HSV();
    bmpRect = new Rect(0, 0, 1, 1);
    this.initialColor = initialColor;
    currentColor = initialColor;
    sliderColor = (UI.isAndroidThemeLight() ? 0xff000000 : 0xffffffff);
    final LinearLayout l = new LinearLayout(context);
    l.setId(1);
    l.setWeightSum(2);
    LayoutParams p = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
    p.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE);
    p.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
    p.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE);
    addView(l, p);
    final TextView lbl = new TextView(context);
    lbl.setBackgroundDrawable(new ColorDrawable(initialColor));
    LinearLayout.LayoutParams lp =
        new LinearLayout.LayoutParams(
            LayoutParams.WRAP_CONTENT,
            smallScreen ? (UI.defaultControlSize) >> 1 : UI.defaultControlSize);
    lp.weight = 1;
    lp.rightMargin = UI.controlSmallMargin;
    l.addView(lbl, lp);
    bgCurrent = new ColorDrawable(initialColor);
    lblCurrent = new TextView(context);
    lblCurrent.setBackgroundDrawable(bgCurrent);
    lp =
        new LinearLayout.LayoutParams(
            LayoutParams.WRAP_CONTENT,
            smallScreen ? (UI.defaultControlSize) >> 1 : UI.defaultControlSize);
    lp.weight = 1;
    lp.leftMargin = UI.controlSmallMargin;
    l.addView(lblCurrent, lp);

    final int textSize = (smallScreen ? UI._14sp : UI._18sp);
    TextView lblTit = new TextView(context);
    lblTit.setId(2);
    lblTit.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
    lblTit.setSingleLine();
    lblTit.setGravity(Gravity.CENTER);
    lblTit.setText("H");
    p = new LayoutParams(eachW, LayoutParams.WRAP_CONTENT);
    p.topMargin = UI.dialogMargin;
    p.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE);
    p.addRule(RelativeLayout.BELOW, 1);
    addView(lblTit, p);
    lblTit = new TextView(context);
    lblTit.setId(3);
    lblTit.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
    lblTit.setSingleLine();
    lblTit.setGravity(Gravity.CENTER);
    lblTit.setText("S");
    p = new LayoutParams(eachW, LayoutParams.WRAP_CONTENT);
    p.topMargin = UI.dialogMargin;
    p.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
    p.addRule(RelativeLayout.BELOW, 1);
    addView(lblTit, p);
    lblTit = new TextView(context);
    lblTit.setId(4);
    lblTit.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
    lblTit.setSingleLine();
    lblTit.setGravity(Gravity.CENTER);
    lblTit.setText("V");
    p = new LayoutParams(eachW, LayoutParams.WRAP_CONTENT);
    p.topMargin = UI.dialogMargin;
    p.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
    p.addRule(RelativeLayout.BELOW, 1);
    addView(lblTit, p);

    barH = new BgSeekBar(context);
    barH.setId(5);
    barH.setMax(360);
    barH.setValue((int) (hsv.h * 360.0));
    barH.setSliderMode(true);
    barH.setVertical(true);
    p = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    p.topMargin = UI.dialogMargin;
    p.leftMargin = ((eachW - UI.defaultControlSize) >> 1);
    p.addRule(RelativeLayout.ALIGN_LEFT, 2);
    p.addRule(RelativeLayout.BELOW, 2);
    p.addRule(RelativeLayout.ABOVE, 6);
    addView(barH, p);
    barS = new BgSeekBar(context);
    barS.setMax(100);
    barS.setValue((int) (hsv.s * 100.0));
    barS.setSliderMode(true);
    barS.setVertical(true);
    p = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    p.topMargin = UI.dialogMargin;
    p.leftMargin = ((eachW - UI.defaultControlSize) >> 1);
    p.addRule(RelativeLayout.ALIGN_LEFT, 3);
    p.addRule(RelativeLayout.BELOW, 3);
    p.addRule(RelativeLayout.ABOVE, 6);
    addView(barS, p);
    barV = new BgSeekBar(context);
    barV.setMax(100);
    barV.setValue((int) (hsv.v * 100.0));
    barV.setSliderMode(true);
    barV.setVertical(true);
    p = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    p.topMargin = UI.dialogMargin;
    p.leftMargin = ((eachW - UI.defaultControlSize) >> 1);
    p.addRule(RelativeLayout.ALIGN_LEFT, 4);
    p.addRule(RelativeLayout.BELOW, 4);
    p.addRule(RelativeLayout.ABOVE, 6);
    addView(barV, p);

    txtH = new EditText(context);
    txtH.setId(6);
    txtH.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
    txtH.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
    txtH.setSingleLine();
    txtH.setGravity(Gravity.CENTER);
    txtH.setText(Integer.toString((int) (hsv.h * 360.0)));
    p = new LayoutParams(eachW, LayoutParams.WRAP_CONTENT);
    p.topMargin = UI.dialogMargin;
    p.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE);
    p.addRule(RelativeLayout.ABOVE, 7);
    addView(txtH, p);
    txtS = new EditText(context);
    txtS.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
    txtS.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
    txtS.setSingleLine();
    txtS.setGravity(Gravity.CENTER);
    txtS.setText(Integer.toString((int) (hsv.s * 100.0)));
    p = new LayoutParams(eachW, LayoutParams.WRAP_CONTENT);
    p.topMargin = UI.dialogMargin;
    p.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
    p.addRule(RelativeLayout.ABOVE, 7);
    addView(txtS, p);
    txtV = new EditText(context);
    txtV.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
    txtV.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
    txtV.setSingleLine();
    txtV.setGravity(Gravity.CENTER);
    txtV.setText(Integer.toString((int) (hsv.v * 100.0)));
    p = new LayoutParams(eachW, LayoutParams.WRAP_CONTENT);
    p.topMargin = UI.dialogMargin;
    p.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
    p.addRule(RelativeLayout.ABOVE, 7);
    addView(txtV, p);

    txt = new EditText(context);
    txt.setId(7);
    txt.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
    txt.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
    txt.setSingleLine();
    txt.setGravity(Gravity.CENTER);
    txt.setText(ColorUtils.toHexColor(initialColor));
    p = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
    p.topMargin = UI.dialogMargin;
    p.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE);
    p.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
    p.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
    addView(txt, p);

    lbl.setOnClickListener(this);
    barH.setOnBgSeekBarChangeListener(this);
    barH.setOnBgSeekBarDrawListener(this);
    barS.setOnBgSeekBarChangeListener(this);
    barS.setOnBgSeekBarDrawListener(this);
    barV.setOnBgSeekBarChangeListener(this);
    barV.setOnBgSeekBarDrawListener(this);
    txtH.addTextChangedListener(this);
    txtS.addTextChangedListener(this);
    txtV.addTextChangedListener(this);
    txt.addTextChangedListener(this);
  }