如何让浮动标签出现在我的EditText的右侧 这是我的MaterialEditText类 我确定我应该改变这一行:
// draw the floating label
canvas.drawText(getHint().toString(), getPaddingLeft() + getScrollX(), position, paint);
但是怎么???
这是我的代码:
public class MaterialEditText extends EditText {
public static final int FLOATING_LABEL_NONE = 0;
public static final int FLOATING_LABEL_NORMAL = 1;
public static final int FLOATING_LABEL_HIGHLIGHT = 2;
/**
* the spacing between the main text and the inner top padding.
*/
private int extraPaddingTop;
/**
* the spacing between the main text and the inner bottom padding.
*/
private int extraPaddingBottom;
/**
* the floating label's text size.
*/
private final int floatingLabelTextSize;
/**
* the spacing between the main text and the inner components (floating label, bottom ellipsis, characters counter).
*/
private final int innerComponentsSpacing;
/**
* whether the floating label should be shown. default is false.
*/
private boolean floatingLabelEnabled;
/**
* whether to highlight the floating label's text color when focused (with the main color). default is true.
*/
private boolean highlightFloatingLabel;
/**
* the base color of the line and the texts. default is black.
*/
private int baseColor;
/**
* inner top padding
*/
private int innerPaddingTop;
/**
* inner bottom padding
*/
private int innerPaddingBottom;
/**
* the underline's highlight color, and the highlight color of the floating label if app:highlightFloatingLabel is set true in the xml. default is black(when app:darkTheme is false) or white(when app:darkTheme is true)
*/
private int primaryColor;
/**
* the color for when something is wrong.(e.g. exceeding max characters)
*/
private int errorColor;
/**
* characters count limit. 0 means no limit. default is 0. NOTE: the character counter will increase the View's height.
*/
private int maxCharacters;
/**
* whether to show the bottom ellipsis in singleLine mode. default is false. NOTE: the bottom ellipsis will increase the View's height.
*/
private boolean singleLineEllipsis;
/**
* bottom ellipsis's height
*/
private final int bottomEllipsisSize;
/**
* animation fraction of the floating label (0 as totally hidden).
*/
private float floatingLabelFraction;
/**
* whether the floating label is being shown.
*/
private boolean floatingLabelShown;
/**
* the floating label's focusFraction
*/
private float focusFraction;
private ArgbEvaluator focusEvaluator = new ArgbEvaluator();
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
ObjectAnimator labelAnimator;
ObjectAnimator labelFocusAnimator;
OnFocusChangeListener interFocusChangeListener;
OnFocusChangeListener outerFocusChangeListener;
public MaterialEditText(Context context) {
this(context, null);
}
public MaterialEditText(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@SuppressLint("NewApi")
public MaterialEditText(Context context, AttributeSet attrs, int style) {
super(context, attrs, style);
setFocusable(true);
setFocusableInTouchMode(true);
setClickable(true);
floatingLabelTextSize = getResources().getDimensionPixelSize(R.dimen.floating_label_text_size);
innerComponentsSpacing = getResources().getDimensionPixelSize(R.dimen.inner_components_spacing);
bottomEllipsisSize = getResources().getDimensionPixelSize(R.dimen.bottom_ellipsis_height);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MaterialEditText);
baseColor = typedArray.getColor(R.styleable.MaterialEditText_baseColor, Color.BLACK);
ColorStateList colorStateList = new ColorStateList(new int[][] {new int[] {android.R.attr.state_enabled}, EMPTY_STATE_SET}, new int[] {baseColor & 0x00ffffff | 0xdf000000, baseColor & 0x00ffffff | 0x44000000});
setTextColor(colorStateList);
primaryColor = typedArray.getColor(R.styleable.MaterialEditText_primaryColor, baseColor);
setFloatingLabelInternal(typedArray.getInt(R.styleable.MaterialEditText_floatingLabel, 0));
errorColor = typedArray.getColor(R.styleable.MaterialEditText_errorColor, Color.parseColor("#e7492E"));
maxCharacters = typedArray.getInt(R.styleable.MaterialEditText_maxCharacters, 0);
singleLineEllipsis = typedArray.getBoolean(R.styleable.MaterialEditText_singleLineEllipsis, false);
typedArray.recycle();
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
// setBackground(null);
// } else {
// setBackgroundDrawable(null);
// }
setBackgroundDrawable(null);
if (singleLineEllipsis) {
TransformationMethod transformationMethod = getTransformationMethod();
setSingleLine();
setTransformationMethod(transformationMethod);
}
initPadding();
initText();
initFloatingLabel();
}
private void initText() {
if (!TextUtils.isEmpty(getText())) {
CharSequence text = getText();
setText(null);
setHintTextColor(baseColor & 0x00ffffff | 0x44000000);
setText(text);
floatingLabelFraction = 1;
floatingLabelShown = true;
} else {
setHintTextColor(baseColor & 0x00ffffff | 0x44000000);
}
}
private float getFloatingLabelFraction() {
return floatingLabelFraction;
}
private void setFloatingLabelFraction(float floatingLabelFraction) {
this.floatingLabelFraction = floatingLabelFraction;
invalidate();
}
private float getFocusFraction() {
return focusFraction;
}
private void setFocusFraction(float focusFraction) {
this.focusFraction = focusFraction;
invalidate();
}
private int getPixel(int dp) {
return Density.dp2px(getContext(), dp);
}
private void initPadding() {
extraPaddingTop = floatingLabelEnabled ? floatingLabelTextSize + innerComponentsSpacing : innerComponentsSpacing;
extraPaddingBottom = maxCharacters > 0 ? floatingLabelTextSize : singleLineEllipsis ? innerComponentsSpacing + bottomEllipsisSize : 0;
extraPaddingBottom += innerComponentsSpacing * 2;
setPaddings(getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom());
}
/**
* 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);
}
/**
* Use this method instead of {@link #setPadding(int, int, int, int)} to automatically set the paddingTop and the paddingBottom correctly.
*/
public void setPaddings(int left, int top, int right, int bottom) {
innerPaddingTop = top;
innerPaddingBottom = bottom;
super.setPadding(left, top + extraPaddingTop, right, bottom + extraPaddingBottom);
}
/**
* get inner top padding, not the real paddingTop
*/
public int getInnerPaddingTop() {
return innerPaddingTop;
}
/**
* get inner bottom padding, not the real paddingBottom
*/
public int getInnerPaddingBottom() {
return innerPaddingBottom;
}
private void initFloatingLabel() {
if (floatingLabelEnabled) {
// 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 (s.length() == 0) {
if (floatingLabelShown) {
floatingLabelShown = false;
getLabelAnimator().reverse();
}
} else if (!floatingLabelShown) {
floatingLabelShown = true;
if (getLabelAnimator().isStarted()) {
getLabelAnimator().reverse();
} else {
getLabelAnimator().start();
}
}
}
});
if (highlightFloatingLabel) {
// observe the focus state to animate the floating label's text color appropriately
interFocusChangeListener = new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
if (getLabelFocusAnimator().isStarted()) {
getLabelFocusAnimator().reverse();
} else {
getLabelFocusAnimator().start();
}
} else {
getLabelFocusAnimator().reverse();
}
if (outerFocusChangeListener != null) {
outerFocusChangeListener.onFocusChange(v, hasFocus);
}
}
};
super.setOnFocusChangeListener(interFocusChangeListener);
}
}
}
public void setBaseColor(int color) {
baseColor = color;
postInvalidate();
}
public void setPrimaryColor(int color) {
primaryColor = color;
postInvalidate();
}
private void setFloatingLabelInternal(int mode) {
switch (mode) {
case FLOATING_LABEL_NORMAL:
floatingLabelEnabled = true;
highlightFloatingLabel = false;
break;
case FLOATING_LABEL_HIGHLIGHT:
floatingLabelEnabled = true;
highlightFloatingLabel = true;
break;
default:
floatingLabelEnabled = false;
highlightFloatingLabel = false;
break;
}
}
public void setFloatingLabel(int mode) {
setFloatingLabelInternal(mode);
postInvalidate();
}
public void setSingleLineEllipsis() {
setSingleLineEllipsis(true);
}
public void setSingleLineEllipsis(boolean enabled) {
singleLineEllipsis = enabled;
postInvalidate();
}
public int getMaxCharacters() {
return maxCharacters;
}
public void setMaxCharacters(int max) {
maxCharacters = max;
postInvalidate();
}
public void setErrorColor(int color) {
errorColor = color;
postInvalidate();
}
@Override
public void setOnFocusChangeListener(OnFocusChangeListener listener) {
if (interFocusChangeListener == null) {
super.setOnFocusChangeListener(listener);
} else {
outerFocusChangeListener = listener;
}
}
private ObjectAnimator getLabelAnimator() {
if (labelAnimator == null) {
labelAnimator = ObjectAnimator.ofFloat(this, "floatingLabelFraction", 0f, 1f);
}
return labelAnimator;
}
private ObjectAnimator getLabelFocusAnimator() {
if (labelFocusAnimator == null) {
labelFocusAnimator = ObjectAnimator.ofFloat(this, "focusFraction", 0f, 1f);
}
return labelFocusAnimator;
}
@Override
protected void onDraw(Canvas canvas) {
// set the textSize
paint.setTextSize(floatingLabelTextSize);
Typeface mfont = Typeface.createFromAsset(getContext().getAssets(),
"fonts/AraHamahAlHorra-Regular.ttf");
paint.setTypeface(mfont);
// draw the background
float lineStartY = getScrollY() + getHeight() - getPaddingBottom() + innerComponentsSpacing;
if (!isEnabled()) { // disabled
paint.setColor(baseColor & 0x00ffffff | 0x44000000);
float interval = getPixel(1);
for (float startX = 0; startX < getWidth(); startX += interval * 3) {
canvas.drawRect(getScrollX() + startX, lineStartY, getScrollX() + startX + interval, lineStartY + getPixel(1), paint);
}
} else if (hasFocus()) { // focused
if (isExceedingMaxCharacters()) {
paint.setColor(errorColor);
} else {
paint.setColor(primaryColor);
}
canvas.drawRect(getScrollX(), lineStartY, getWidth() + getScrollX(), lineStartY + getPixel(2), paint);
// draw the characters counter
if (maxCharacters > 0) {
if (!isExceedingMaxCharacters()) {
paint.setColor(getCurrentHintTextColor());
}
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
float relativeHeight = -fontMetrics.ascent - fontMetrics.descent;
String text = getText().length() + " / " + maxCharacters;
canvas.drawText(text, getWidth() + getScrollX() - paint.measureText(text), lineStartY + innerComponentsSpacing + relativeHeight, paint);
}
} else { // normal
paint.setColor(baseColor);
canvas.drawRect(getScrollX(), lineStartY, getWidth() + getScrollX(), lineStartY + getPixel(1), paint);
}
// draw the floating label
if (floatingLabelEnabled && !TextUtils.isEmpty(getHint())) {
// calculate the text color
paint.setColor((Integer) focusEvaluator.evaluate(focusFraction, getCurrentHintTextColor(), primaryColor));
// calculate the vertical position
int start = innerPaddingTop + floatingLabelTextSize + innerComponentsSpacing;
int distance = innerComponentsSpacing;
int position = (int) (start - distance * floatingLabelFraction);
// calculate the alpha
int alpha = (int) (floatingLabelFraction * 0xff * (0.74f * focusFraction + 0.26f));
paint.setAlpha(alpha);
// draw the floating label
canvas.drawText(getHint().toString(), getPaddingLeft() + getScrollX(), position, paint);
}
// draw the bottom ellipsis
if (hasFocus() && singleLineEllipsis && getScrollX() != 0) {
paint.setColor(primaryColor);
float startY = lineStartY + innerComponentsSpacing;
canvas.drawCircle(bottomEllipsisSize / 2 + getScrollX(), startY + bottomEllipsisSize / 2, bottomEllipsisSize / 2, paint);
canvas.drawCircle(bottomEllipsisSize * 5 / 2 + getScrollX(), startY + bottomEllipsisSize / 2, bottomEllipsisSize / 2, paint);
canvas.drawCircle(bottomEllipsisSize * 9 / 2 + getScrollX(), startY + bottomEllipsisSize / 2, bottomEllipsisSize / 2, paint);
}
// draw the original things
super.onDraw(canvas);
}
public boolean isExceedingMaxCharacters() {
return maxCharacters > 0 && getText() != null && maxCharacters < getText().length();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (singleLineEllipsis && getScrollX() > 0 && event.getAction() == MotionEvent.ACTION_DOWN && event.getX() < getPixel(4 * 5) && event.getY() > getHeight() - extraPaddingBottom - innerPaddingBottom && event.getY() < getHeight() - innerPaddingBottom) {
setSelection(0);
return false;
}
return super.onTouchEvent(event);
}
并在布局中调用如下:
<net.urengwuxian.materialeditlibrary.MaterialEditText
android:id="@+id/number_trade_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:drawablePadding="10dp"
android:drawableRight="@drawable/ic_edit"
android:gravity="right"
android:hint="@string/number_trade_text_hint"
android:inputType="number"
android:maxLength="5"
android:textSize="20sp"
app:baseColor="@android:color/black"
app:floatingLabel="highlight"
app:maxCharacters="5"
app:primaryColor="@android:color/holo_blue_light" />