-
-
Save alphamu/0d3055e0233c5749b8d6 to your computer and use it in GitHub Desktop.
| import android.annotation.TargetApi; | |
| import android.content.Context; | |
| import android.content.res.ColorStateList; | |
| import android.graphics.Canvas; | |
| import android.graphics.Color; | |
| import android.graphics.Paint; | |
| import android.os.Build; | |
| import android.text.Editable; | |
| import android.util.AttributeSet; | |
| import android.util.TypedValue; | |
| import android.view.ActionMode; | |
| import android.view.Menu; | |
| import android.view.MenuItem; | |
| import android.view.View; | |
| import android.widget.EditText; | |
| public class PinEntryEditText extends EditText { | |
| public static final String XML_NAMESPACE_ANDROID = "http://schemas.android.com/apk/res/android"; | |
| private float mSpace = 24; //24 dp by default, space between the lines | |
| private float mCharSize; | |
| private float mNumChars = 4; | |
| private float mLineSpacing = 8; //8dp by default, height of the text from our lines | |
| private int mMaxLength = 4; | |
| private OnClickListener mClickListener; | |
| private float mLineStroke = 1; //1dp by default | |
| private float mLineStrokeSelected = 2; //2dp by default | |
| private Paint mLinesPaint; | |
| int[][] mStates = new int[][]{ | |
| new int[]{android.R.attr.state_selected}, // selected | |
| new int[]{android.R.attr.state_focused}, // focused | |
| new int[]{-android.R.attr.state_focused}, // unfocused | |
| }; | |
| int[] mColors = new int[]{ | |
| Color.GREEN, | |
| Color.BLACK, | |
| Color.GRAY | |
| }; | |
| ColorStateList mColorStates = new ColorStateList(mStates, mColors); | |
| public PinEntryEditText(Context context) { | |
| super(context); | |
| } | |
| public PinEntryEditText(Context context, AttributeSet attrs) { | |
| super(context, attrs); | |
| init(context, attrs); | |
| } | |
| public PinEntryEditText(Context context, AttributeSet attrs, int defStyleAttr) { | |
| super(context, attrs, defStyleAttr); | |
| init(context, attrs); | |
| } | |
| @TargetApi(Build.VERSION_CODES.LOLLIPOP) | |
| public PinEntryEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { | |
| super(context, attrs, defStyleAttr, defStyleRes); | |
| init(context, attrs); | |
| } | |
| private void init(Context context, AttributeSet attrs) { | |
| float multi = context.getResources().getDisplayMetrics().density; | |
| mLineStroke = multi * mLineStroke; | |
| mLineStrokeSelected = multi * mLineStrokeSelected; | |
| mLinesPaint = new Paint(getPaint()); | |
| mLinesPaint.setStrokeWidth(mLineStroke); | |
| if (!isInEditMode()) { | |
| TypedValue outValue = new TypedValue(); | |
| context.getTheme().resolveAttribute(R.attr.colorControlActivated, | |
| outValue, true); | |
| final int colorActivated = outValue.data; | |
| mColors[0] = colorActivated; | |
| context.getTheme().resolveAttribute(R.attr.colorPrimaryDark, | |
| outValue, true); | |
| final int colorDark = outValue.data; | |
| mColors[1] = colorDark; | |
| context.getTheme().resolveAttribute(R.attr.colorControlHighlight, | |
| outValue, true); | |
| final int colorHighlight = outValue.data; | |
| mColors[2] = colorHighlight; | |
| } | |
| setBackgroundResource(0); | |
| mSpace = multi * mSpace; //convert to pixels for our density | |
| mLineSpacing = multi * mLineSpacing; //convert to pixels for our density | |
| mMaxLength = attrs.getAttributeIntValue(XML_NAMESPACE_ANDROID, "maxLength", 4); | |
| mNumChars = mMaxLength; | |
| //Disable copy paste | |
| super.setCustomSelectionActionModeCallback(new ActionMode.Callback() { | |
| public boolean onPrepareActionMode(ActionMode mode, Menu menu) { | |
| return false; | |
| } | |
| public void onDestroyActionMode(ActionMode mode) { | |
| } | |
| public boolean onCreateActionMode(ActionMode mode, Menu menu) { | |
| return false; | |
| } | |
| public boolean onActionItemClicked(ActionMode mode, MenuItem item) { | |
| return false; | |
| } | |
| }); | |
| // When tapped, move cursor to end of text. | |
| super.setOnClickListener(new OnClickListener() { | |
| @Override | |
| public void onClick(View v) { | |
| setSelection(getText().length()); | |
| if (mClickListener != null) { | |
| mClickListener.onClick(v); | |
| } | |
| } | |
| }); | |
| } | |
| @Override | |
| public void setOnClickListener(OnClickListener l) { | |
| mClickListener = l; | |
| } | |
| @Override | |
| public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) { | |
| throw new RuntimeException("setCustomSelectionActionModeCallback() not supported."); | |
| } | |
| @Override | |
| protected void onDraw(Canvas canvas) { | |
| //super.onDraw(canvas); | |
| int availableWidth = getWidth() - getPaddingRight() - getPaddingLeft(); | |
| if (mSpace < 0) { | |
| mCharSize = (availableWidth / (mNumChars * 2 - 1)); | |
| } else { | |
| mCharSize = (availableWidth - (mSpace * (mNumChars - 1))) / mNumChars; | |
| } | |
| int startX = getPaddingLeft(); | |
| int bottom = getHeight() - getPaddingBottom(); | |
| //Text Width | |
| Editable text = getText(); | |
| int textLength = text.length(); | |
| float[] textWidths = new float[textLength]; | |
| getPaint().getTextWidths(getText(), 0, textLength, textWidths); | |
| for (int i = 0; i < mNumChars; i++) { | |
| updateColorForLines(i == textLength); | |
| canvas.drawLine(startX, bottom, startX + mCharSize, bottom, mLinesPaint); | |
| if (getText().length() > i) { | |
| float middle = startX + mCharSize / 2; | |
| canvas.drawText(text, i, i + 1, middle - textWidths[0] / 2, bottom - mLineSpacing, getPaint()); | |
| } | |
| if (mSpace < 0) { | |
| startX += mCharSize * 2; | |
| } else { | |
| startX += mCharSize + mSpace; | |
| } | |
| } | |
| } | |
| private int getColorForState(int... states) { | |
| return mColorStates.getColorForState(states, Color.GRAY); | |
| } | |
| /** | |
| * @param next Is the current char the next character to be input? | |
| */ | |
| private void updateColorForLines(boolean next) { | |
| if (isFocused()) { | |
| mLinesPaint.setStrokeWidth(mLineStrokeSelected); | |
| mLinesPaint.setColor(getColorForState(android.R.attr.state_focused)); | |
| if (next) { | |
| mLinesPaint.setColor(getColorForState(android.R.attr.state_selected)); | |
| } | |
| } else { | |
| mLinesPaint.setStrokeWidth(mLineStroke); | |
| mLinesPaint.setColor(getColorForState(-android.R.attr.state_focused)); | |
| } | |
| } | |
| } |
| <?xml version="1.0" encoding="utf-8"?> | |
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
| xmlns:tools="http://schemas.android.com/tools" | |
| android:layout_width="match_parent" | |
| android:layout_height="match_parent" | |
| android:clipChildren="false" | |
| android:clipToPadding="false" | |
| android:orientation="vertical" | |
| android:padding="@dimen/activity_horizontal_margin" | |
| tools:context="com.alimuzaffar.customwidgets.MainActivity"> | |
| <TextView | |
| android:textAppearance="@android:style/TextAppearance.Large" | |
| android:text="Please enter PIN" | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" /> | |
| <com.alimuzaffar.customwidgets.PinEntryEditText | |
| android:id="@+id/txt_pin_entry" | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:cursorVisible="false" | |
| android:digits="1234567890" | |
| android:inputType="number" | |
| android:maxLength="4" | |
| android:textIsSelectable="false" | |
| android:textSize="20sp" /> | |
| <EditText | |
| android:layout_width="match_parent" | |
| android:layout_height="wrap_content" | |
| android:layout_marginTop="32dp" | |
| android:hint="Regular EditText"/> | |
| </LinearLayout> |
| import android.support.v7.app.AppCompatActivity; | |
| import android.os.Bundle; | |
| import android.text.Editable; | |
| import android.text.TextWatcher; | |
| import android.widget.Toast; | |
| public class MainActivity extends AppCompatActivity { | |
| @Override | |
| protected void onCreate(Bundle savedInstanceState) { | |
| super.onCreate(savedInstanceState); | |
| setContentView(R.layout.activity_main); | |
| final PinEntryEditText txtPinEntry = (PinEntryEditText) findViewById(R.id.txt_pin_entry); | |
| txtPinEntry.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.toString().equals("1234")) { | |
| Toast.makeText(MainActivity.this, "Success", Toast.LENGTH_SHORT).show(); | |
| } else if (s.length() == "1234".length()) { | |
| Toast.makeText(MainActivity.this, "Incorrect", Toast.LENGTH_SHORT).show(); | |
| txtPinEntry.setText(null); | |
| } | |
| } | |
| }); | |
| } | |
| } |
Excellent Job.
However, I am not being able to change the text color in PinEntryEditText.
I tried changing it from XML and progammatically thinking it would work as if it would work for EditText because the class is extending EditText class . But, I have had no luck with this? Is there any way to do so?
I am not able to change the text color? tried both in xml and programatically? please let me know how can be changed?
To change text color use getPaint().setColor(Color.parseColor("#FFFFFF")). You can write this on line 152.
there is error getting width of character
canvas.drawText(text, i, i + 1, middle - textWidths[0] / 2, bottom - mLineSpacing, getPaint());
should be
canvas.drawText(text, i, i + 1, middle - textWidths[i] / 2, bottom - mLineSpacing, getPaint());
for AndroidX extend androidx.appcompat.widget.AppCompatEditText instead of Edittext
--To change text color following this line write in PinEntryEditText.java class
To change text color use getPaint().setColor(Color.parseColor("#FFFFFF")). You can write this on line 152.
--To change edit text underline color to write following line in PinEntryEditText
Replace colorControlActivated, colorPrimaryDark, colorControlHighlight To "colorBackgroundFloating"
android:cursorVisible="true"
cursor is not visible.
How can change to a password edittext? Setting the attribute in XML or programmatically does not work
How can change to a password edittext? Setting the attribute in XML or programmatically does not work
what have you tried?
Have you tried
android:inputType="password"
?
i tried but its not working numbers are visible when input
Excellent Job.
However, I am not being able to change the text color in PinEntryEditText.
I tried changing it from XML and progammatically thinking it would work as if it would work for EditText because the class is extending EditText class . But, I have had no luck with this? Is there any way to do so?