@Override
 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
   super.onLayout(changed, left, top, right, bottom);
   if (changed) {
     adjustBottomLines();
   }
 }
 @Override
 protected void onAttachedToWindow() {
   super.onAttachedToWindow();
   if (!firstShown) {
     firstShown = true;
   }
 }
 @Override
 public void setOnFocusChangeListener(OnFocusChangeListener listener) {
   if (innerFocusChangeListener == null) {
     super.setOnFocusChangeListener(listener);
   } else {
     outerFocusChangeListener = listener;
   }
 }
 /** Set paddings to the correct values */
 private void correctPaddings() {
   int buttonsWidthLeft = 0, buttonsWidthRight = 0;
   int buttonsWidth = iconOuterWidth * getButtonsCount();
   if (isRTL()) {
     buttonsWidthLeft = buttonsWidth;
   } else {
     buttonsWidthRight = buttonsWidth;
   }
   super.setPadding(
       innerPaddingLeft + extraPaddingLeft + buttonsWidthLeft,
       innerPaddingTop + extraPaddingTop,
       innerPaddingRight + extraPaddingRight + buttonsWidthRight,
       innerPaddingBottom + extraPaddingBottom);
 }
  private void initFloatingLabel() {
    // observe the text changing
    addTextChangedListener(
        new TextWatcher() {
          @Override
          public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

          @Override
          public void onTextChanged(CharSequence s, int start, int before, int count) {}

          @Override
          public void afterTextChanged(Editable s) {
            if (floatingLabelEnabled) {
              if (s.length() == 0) {
                if (floatingLabelShown) {
                  floatingLabelShown = false;
                  getLabelAnimator().reverse();
                }
              } else if (!floatingLabelShown) {
                floatingLabelShown = true;
                getLabelAnimator().start();
              }
            }
          }
        });
    // observe the focus state to animate the floating label's text color appropriately
    innerFocusChangeListener =
        new OnFocusChangeListener() {
          @Override
          public void onFocusChange(View v, boolean hasFocus) {
            if (floatingLabelEnabled && highlightFloatingLabel) {
              if (hasFocus) {
                getLabelFocusAnimator().start();
              } else {
                getLabelFocusAnimator().reverse();
              }
            }
            if (validateOnFocusLost && !hasFocus) {
              validate();
            }
            if (outerFocusChangeListener != null) {
              outerFocusChangeListener.onFocusChange(v, hasFocus);
            }
          }
        };
    super.setOnFocusChangeListener(innerFocusChangeListener);
  }
 /**
  * use {@link #setPaddings(int, int, int, int)} instead, or the paddingTop and the paddingBottom
  * may be set incorrectly.
  */
 @Deprecated
 @Override
 public final void setPadding(int left, int top, int right, int bottom) {
   super.setPadding(left, top, right, bottom);
 }
  @Override
  protected void onDraw(@NonNull Canvas canvas) {
    int startX = getScrollX() + (iconLeftBitmaps == null ? 0 : (iconOuterWidth + iconPadding));
    int endX =
        getScrollX()
            + (iconRightBitmaps == null ? getWidth() : getWidth() - iconOuterWidth - iconPadding);
    int lineStartY = getScrollY() + getHeight() - getPaddingBottom();

    // draw the icon(s)
    paint.setAlpha(255);
    if (iconLeftBitmaps != null) {
      Bitmap icon = iconLeftBitmaps[!isInternalValid() ? 3 : !isEnabled() ? 2 : hasFocus() ? 1 : 0];
      int iconLeft = startX - iconPadding - iconOuterWidth + (iconOuterWidth - icon.getWidth()) / 2;
      int iconTop =
          lineStartY + bottomSpacing - iconOuterHeight + (iconOuterHeight - icon.getHeight()) / 2;
      canvas.drawBitmap(icon, iconLeft, iconTop, paint);
    }
    if (iconRightBitmaps != null) {
      Bitmap icon =
          iconRightBitmaps[!isInternalValid() ? 3 : !isEnabled() ? 2 : hasFocus() ? 1 : 0];
      int iconRight = endX + iconPadding + (iconOuterWidth - icon.getWidth()) / 2;
      int iconTop =
          lineStartY + bottomSpacing - iconOuterHeight + (iconOuterHeight - icon.getHeight()) / 2;
      canvas.drawBitmap(icon, iconRight, iconTop, paint);
    }

    // draw the clear button
    if (hasFocus() && showClearButton && !TextUtils.isEmpty(getText()) && isEnabled()) {
      paint.setAlpha(255);
      int buttonLeft;
      if (isRTL()) {
        buttonLeft = startX;
      } else {
        buttonLeft = endX - iconOuterWidth;
      }
      Bitmap clearButtonBitmap = clearButtonBitmaps[0];
      buttonLeft += (iconOuterWidth - clearButtonBitmap.getWidth()) / 2;
      int iconTop =
          lineStartY
              + bottomSpacing
              - iconOuterHeight
              + (iconOuterHeight - clearButtonBitmap.getHeight()) / 2;
      canvas.drawBitmap(clearButtonBitmap, buttonLeft, iconTop, paint);
    }

    // draw the underline
    if (!hideUnderline) {
      lineStartY += bottomSpacing;
      if (!isInternalValid()) { // not valid
        paint.setColor(errorColor);
        canvas.drawRect(startX, lineStartY, endX, lineStartY + getPixel(2), paint);
      } else if (!isEnabled()) { // disabled
        paint.setColor(underlineColor != -1 ? underlineColor : baseColor & 0x00ffffff | 0x44000000);
        float interval = getPixel(1);
        for (float xOffset = 0; xOffset < getWidth(); xOffset += interval * 3) {
          canvas.drawRect(
              startX + xOffset,
              lineStartY,
              startX + xOffset + interval,
              lineStartY + getPixel(1),
              paint);
        }
      } else if (hasFocus()) { // focused
        paint.setColor(primaryColor);
        canvas.drawRect(startX, lineStartY, endX, lineStartY + getPixel(2), paint);
      } else { // normal
        paint.setColor(underlineColor != -1 ? underlineColor : baseColor & 0x00ffffff | 0x1E000000);
        canvas.drawRect(startX, lineStartY, endX, lineStartY + getPixel(1), paint);
      }
    }

    textPaint.setTextSize(bottomTextSize);
    Paint.FontMetrics textMetrics = textPaint.getFontMetrics();
    float relativeHeight = -textMetrics.ascent - textMetrics.descent;
    float bottomTextPadding = bottomTextSize + textMetrics.ascent + textMetrics.descent;

    // draw the characters counter
    if ((hasFocus() && hasCharactersCounter()) || !isCharactersCountValid()) {
      textPaint.setColor(
          isCharactersCountValid() ? (baseColor & 0x00ffffff | 0x44000000) : errorColor);
      String charactersCounterText = getCharactersCounterText();
      canvas.drawText(
          charactersCounterText,
          isRTL() ? startX : endX - textPaint.measureText(charactersCounterText),
          lineStartY + bottomSpacing + relativeHeight,
          textPaint);
    }

    // draw the bottom text
    if (textLayout != null) {
      if (tempErrorText != null
          || ((helperTextAlwaysShown || hasFocus())
              && !TextUtils.isEmpty(helperText))) { // error text or helper text
        textPaint.setColor(
            tempErrorText != null
                ? errorColor
                : helperTextColor != -1 ? helperTextColor : (baseColor & 0x00ffffff | 0x44000000));
        canvas.save();
        if (isRTL()) {
          canvas.translate(
              endX - textLayout.getWidth(), lineStartY + bottomSpacing - bottomTextPadding);
        } else {
          canvas.translate(
              startX + getBottomTextLeftOffset(), lineStartY + bottomSpacing - bottomTextPadding);
        }
        textLayout.draw(canvas);
        canvas.restore();
      }
    }

    // draw the floating label
    if (floatingLabelEnabled && !TextUtils.isEmpty(floatingLabelText)) {
      textPaint.setTextSize(floatingLabelTextSize);
      // calculate the text color
      textPaint.setColor(
          (Integer)
              focusEvaluator.evaluate(
                  focusFraction * (isEnabled() ? 1 : 0),
                  floatingLabelTextColor != -1
                      ? floatingLabelTextColor
                      : (baseColor & 0x00ffffff | 0x44000000),
                  primaryColor));

      // calculate the horizontal position
      float floatingLabelWidth = textPaint.measureText(floatingLabelText.toString());
      int floatingLabelStartX;
      if ((getGravity() & Gravity.RIGHT) == Gravity.RIGHT || isRTL()) {
        floatingLabelStartX = (int) (endX - floatingLabelWidth);
      } else if ((getGravity() & Gravity.LEFT) == Gravity.LEFT) {
        floatingLabelStartX = startX;
      } else {
        floatingLabelStartX =
            startX
                + (int)
                    (getInnerPaddingLeft()
                        + (getWidth()
                                - getInnerPaddingLeft()
                                - getInnerPaddingRight()
                                - floatingLabelWidth)
                            / 2);
      }

      // calculate the vertical position
      int distance = floatingLabelPadding;
      int floatingLabelStartY =
          (int)
              (innerPaddingTop
                  + floatingLabelTextSize
                  + floatingLabelPadding
                  - distance * (floatingLabelAlwaysShown ? 1 : floatingLabelFraction)
                  + getScrollY());

      // calculate the alpha
      int alpha =
          ((int)
              ((floatingLabelAlwaysShown ? 1 : floatingLabelFraction)
                  * 0xff
                  * (0.74f * focusFraction * (isEnabled() ? 1 : 0) + 0.26f)
                  * (floatingLabelTextColor != -1
                      ? 1
                      : Color.alpha(floatingLabelTextColor) / 256f)));
      textPaint.setAlpha(alpha);

      // draw the floating label
      canvas.drawText(
          floatingLabelText.toString(), floatingLabelStartX, floatingLabelStartY, textPaint);
    }

    // draw the bottom ellipsis
    if (hasFocus() && singleLineEllipsis && getScrollX() != 0) {
      paint.setColor(isInternalValid() ? primaryColor : errorColor);
      float startY = lineStartY + bottomSpacing;
      int ellipsisStartX;
      if (isRTL()) {
        ellipsisStartX = endX;
      } else {
        ellipsisStartX = startX;
      }
      int signum = isRTL() ? -1 : 1;
      canvas.drawCircle(
          ellipsisStartX + signum * bottomEllipsisSize / 2,
          startY + bottomEllipsisSize / 2,
          bottomEllipsisSize / 2,
          paint);
      canvas.drawCircle(
          ellipsisStartX + signum * bottomEllipsisSize * 5 / 2,
          startY + bottomEllipsisSize / 2,
          bottomEllipsisSize / 2,
          paint);
      canvas.drawCircle(
          ellipsisStartX + signum * bottomEllipsisSize * 9 / 2,
          startY + bottomEllipsisSize / 2,
          bottomEllipsisSize / 2,
          paint);
    }

    // draw the original things
    super.onDraw(canvas);
  }