Skip to content

Commit

Permalink
Merge pull request #12 from poovamraj/CORNER_RADIUS_PASSWORD_MASK_FEA…
Browse files Browse the repository at this point in the history
…TURE

Merge branch "CORNER_RADIUS_PASSWORD_MASK_FEATURE" to "master"
  • Loading branch information
poovamraj authored Oct 27, 2018
2 parents e813179 + dbcc930 commit 38da30d
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 44 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ apply plugin: 'kotlin-android-extensions'
ext {
PUBLISH_GROUP_ID = 'com.poovam'
PUBLISH_ARTIFACT_ID = 'pin-edittext-field'
PUBLISH_VERSION = '1.0.9'
PUBLISH_VERSION = '1.1.0'
}

android {
Expand Down
65 changes: 56 additions & 9 deletions app/src/main/java/com/poovam/pinedittextfield/CirclePinField.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import android.graphics.Canvas
import android.graphics.Paint
import android.support.v4.content.ContextCompat
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup

/**
* Created by poovam-5255 on 5/23/2018.
Expand All @@ -14,7 +16,7 @@ import android.util.AttributeSet
*/
class CirclePinField: PinField{

var fillerColor = ContextCompat.getColor(context,R.color.accent)
var fillerColor = ContextCompat.getColor(context,R.color.pinFieldLibraryAccent)
set(value){
field = value
fillerPaint.color = fillerColor
Expand Down Expand Up @@ -46,6 +48,7 @@ class CirclePinField: PinField{
try {
circleRadiusDp = a.getDimension(R.styleable.CirclePinField_circleRadius, circleRadiusDp)
fillerColor = a.getColor(R.styleable.CirclePinField_fillerColor, fillerColor)
if(distanceInBetween == DEFAULT_DISTANCE_IN_BETWEEN) distanceInBetween = Util.dpToPx(30f)
} finally {
a.recycle()
}
Expand All @@ -55,36 +58,80 @@ class CirclePinField: PinField{
fillerPaint.strokeWidth = circleRadiusDp
}

override fun getDefaultDistanceInBetween(): Float{
return (singleFieldWidth - (circleRadiusDp*2))*2
override fun getViewWidth(desiredWidth:Int, widthMeasureSpec: Int): Int {

val widthMode = View.MeasureSpec.getMode(widthMeasureSpec)
val widthSize = View.MeasureSpec.getSize(widthMeasureSpec)
val viewWidth = getCircleDiameterWithPadding() * numberOfFields
//Measure Width
return when (widthMode) {
MeasureSpec.EXACTLY -> widthSize
MeasureSpec.AT_MOST -> Math.min(viewWidth, widthSize)
MeasureSpec.UNSPECIFIED -> viewWidth
else -> viewWidth
}
}

private fun getCircleDiameterWithPadding():Int{
val diameter = circleRadiusDp*2
return Math.round(diameter + getThickness() + getPadding())
}

/**
* This will return thickness based on the chosen mode
* there will be a small padding even if distanceInBetween = 0dp if there is a highlight
* this is to make sure when highlighting there is no overlap
*/
private fun getThickness(): Int{
return Math.round(if(isHighlightEnabled)highLightThickness else lineThickness)
}

private fun getPadding(): Float{
return if (distanceInBetween!= DEFAULT_DISTANCE_IN_BETWEEN) distanceInBetween else getDefaultDistanceInBetween()/2
}

override fun onDraw(canvas: Canvas?) {

for (i in 0 until numberOfFields){
var startingX = (width - (getCircleDiameterWithPadding()*numberOfFields))/2

val padding = (if (distanceInBetween!= defDistanceInBetweenValue) distanceInBetween else getDefaultDistanceInBetween())/2
startingX = if(startingX > 0) startingX else 0

val x1 = (padding+(circleRadiusDp*2))*i
val x1 = (getCircleDiameterWithPadding().toFloat() * i) + getCircleDiameterWithPadding()/2 + startingX

val character:Char? = text?.getOrNull(i)

val y1 = getViewHeight(height)

if(isHighlightEnabled && !highlightSingleFieldMode && hasFocus()){
canvas?.drawCircle(x1+(singleFieldWidth/2).toFloat(),(height/2).toFloat(),circleRadiusDp, highlightPaint)
canvas?.drawCircle(x1,y1,circleRadiusDp, highlightPaint)
}else{
canvas?.drawCircle(x1+(singleFieldWidth/2).toFloat(),(height/2).toFloat(),circleRadiusDp, fieldPaint)
canvas?.drawCircle(x1,y1,circleRadiusDp, fieldPaint)
}

if(character!=null) {
canvas?.drawCircle(x1+(singleFieldWidth/2).toFloat(),(height/2).toFloat(),(circleRadiusDp/2)-highLightThickness, fillerPaint)
canvas?.drawCircle(x1,y1,(circleRadiusDp/2)-highLightThickness, fillerPaint)
}

if(hasFocus() && i == text?.length ?: 0){
if(isHighlightEnabled && highlightSingleFieldMode){
canvas?.drawCircle(x1+(singleFieldWidth/2).toFloat(),(height/2).toFloat(),circleRadiusDp, highlightPaint)
canvas?.drawCircle(x1,y1,circleRadiusDp, highlightPaint)
}
}
}
}

/**
* This is a dirty hack since the height provided by Android framework seems same
* but drawing it on canvas seems to draw out of frame
* Need to look into this more
*/
private fun getViewHeight(height: Int): Float{
if(!isCustomBackground && this.layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT
&& getPadding() < circleRadiusDp){
return (height - getPadding()*1.5).toFloat()
}
return height/2.toFloat()
}

}
28 changes: 22 additions & 6 deletions app/src/main/java/com/poovam/pinedittextfield/LinePinField.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,40 @@ class LinePinField : PinField {

private val cursorBottomPadding = Util.dpToPx(2f)

var bottomTextPaddingDp = 0f


constructor(context: Context): super(context)

constructor(context: Context, attr: AttributeSet) : super(context,attr)
constructor(context: Context, attr: AttributeSet) : super(context,attr){
initParams(attr)
}

constructor(context: Context, attr: AttributeSet, defStyle: Int) : super(context,attr,defStyle)
constructor(context: Context,attr: AttributeSet,defStyle: Int) : super(context,attr,defStyle){
initParams(attr)
}

private fun initParams(attr: AttributeSet){
val a = context.theme.obtainStyledAttributes(attr, R.styleable.LinePinField, 0,0)
try {
bottomTextPaddingDp = a.getDimension(R.styleable.LinePinField_bottomTextPaddingDp,bottomTextPaddingDp)
} finally {
a.recycle()
}
}

override fun onDraw(canvas: Canvas?) {

for (i in 0 until numberOfFields){

val x1 = (i*singleFieldWidth)
val padding = (if (distanceInBetween!= defDistanceInBetweenValue) distanceInBetween else getDefaultDistanceInBetween())/2
val padding = (if (distanceInBetween!= DEFAULT_DISTANCE_IN_BETWEEN) distanceInBetween else getDefaultDistanceInBetween())/2
val paddedX1 = (x1 + padding)
val paddedX2 = ((x1+singleFieldWidth)-padding)
val paddedY1 = height - yPadding
val textX = ((paddedX2-paddedX1)/2)+paddedX1
val textY = (paddedY1- lineThickness)-(textPaint.textSize/4)
val character:Char? = text?.getOrNull(i)
val textY = (paddedY1- lineThickness)-(textPaint.textSize/4)-bottomTextPaddingDp
val character:Char? = transformationMethod?.getTransformation(text,this)?.getOrNull(i) ?: text.getOrNull(i)

if(isHighlightEnabled && !highlightSingleFieldMode && hasFocus()){
canvas?.drawLine(paddedX1,paddedY1,paddedX2,paddedY1, highlightPaint)
Expand All @@ -46,7 +62,7 @@ class LinePinField : PinField {

if(hasFocus() && i == text?.length ?: 0){
if(isCursorEnabled){
val cursorY1 = paddedY1 - cursorBottomPadding - highLightThickness
val cursorY1 = paddedY1 - cursorBottomPadding - highLightThickness - bottomTextPaddingDp
val cursorY2 = cursorTopPadding
drawCursor(canvas,textX ,cursorY1,cursorY2,highlightPaint)
}
Expand Down
40 changes: 22 additions & 18 deletions app/src/main/java/com/poovam/pinedittextfield/PinField.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ open class PinField : AppCompatEditText {

private val defaultWidth = Util.dpToPx(60f).toInt()

protected val defDistanceInBetweenValue = -1f
companion object {
val DEFAULT_DISTANCE_IN_BETWEEN = -1f
}

protected var distanceInBetween:Float = defDistanceInBetweenValue
protected var distanceInBetween:Float = DEFAULT_DISTANCE_IN_BETWEEN
set(value) {
field = value
requestLayout()
Expand Down Expand Up @@ -53,7 +55,7 @@ open class PinField : AppCompatEditText {
invalidate()
}

var highlightPaintColor = ContextCompat.getColor(context,R.color.accent)
var highlightPaintColor = ContextCompat.getColor(context,R.color.pinFieldLibraryAccent)
set(value){
field = value
highlightPaint.color = field
Expand Down Expand Up @@ -87,7 +89,7 @@ open class PinField : AppCompatEditText {
var isCustomBackground = false
set(value) {
if(!value){
setBackgroundResource(R.color.transparent)
setBackgroundResource(R.color.pinFieldLibraryTransparent)
}
field = value
}
Expand Down Expand Up @@ -136,7 +138,7 @@ open class PinField : AppCompatEditText {
try {
numberOfFields = a.getInt(R.styleable.PinField_noOfFields, numberOfFields)
lineThickness = a.getDimension(R.styleable.PinField_lineThickness, lineThickness)
distanceInBetween = a.getDimension(R.styleable.PinField_distanceInBetween, defDistanceInBetweenValue)
distanceInBetween = a.getDimension(R.styleable.PinField_distanceInBetween, DEFAULT_DISTANCE_IN_BETWEEN)
fieldColor = a.getColor(R.styleable.PinField_fieldColor,fieldColor)
highlightPaintColor = a.getColor(R.styleable.PinField_highlightColor,highlightPaintColor)
isHighlightEnabled = a.getBoolean(R.styleable.PinField_highlightEnabled,isHighlightEnabled)
Expand All @@ -149,36 +151,35 @@ open class PinField : AppCompatEditText {
}

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val width = getViewWidth(defaultWidth * numberOfFields,widthMeasureSpec)
singleFieldWidth = width/numberOfFields
setMeasuredDimension(width, getViewHeight(singleFieldWidth,heightMeasureSpec))
}

val desiredWidth = (defaultWidth * numberOfFields)
open protected fun getViewWidth(desiredWidth:Int, widthMeasureSpec: Int): Int{
val widthMode = View.MeasureSpec.getMode(widthMeasureSpec)
val widthSize = View.MeasureSpec.getSize(widthMeasureSpec)
val width: Int

//Measure Width
width = when (widthMode) {
View.MeasureSpec.EXACTLY -> widthSize
View.MeasureSpec.AT_MOST -> Math.min(desiredWidth, widthSize)
View.MeasureSpec.UNSPECIFIED -> desiredWidth
return when (widthMode) {
MeasureSpec.EXACTLY -> widthSize
MeasureSpec.AT_MOST -> Math.min(desiredWidth, widthSize)
MeasureSpec.UNSPECIFIED -> desiredWidth
else -> desiredWidth
}
singleFieldWidth = width/numberOfFields

}

val desiredHeight = singleFieldWidth
open protected fun getViewHeight(desiredHeight: Int, heightMeasureSpec: Int): Int{
val heightMode = View.MeasureSpec.getMode(heightMeasureSpec)
val heightSize = View.MeasureSpec.getSize(heightMeasureSpec)
val height: Int

//Measure Height
height = when (heightMode) {
return when (heightMode) {
View.MeasureSpec.EXACTLY -> heightSize
View.MeasureSpec.AT_MOST -> Math.min(desiredHeight, heightSize)
View.MeasureSpec.UNSPECIFIED -> desiredHeight
else -> desiredHeight
}

setMeasuredDimension(width, height)
}

override fun onSelectionChanged(selStart: Int, selEnd: Int) {
Expand Down Expand Up @@ -232,6 +233,9 @@ open class PinField : AppCompatEditText {
}

interface OnTextCompleteListener {
/**
* @return return true if keyboard should be closed after text is entered
*/
fun onTextComplete(enteredText: String): Boolean
}
}
42 changes: 35 additions & 7 deletions app/src/main/java/com/poovam/pinedittextfield/SquarePinField.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.poovam.pinedittextfield

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.os.Build
import android.util.AttributeSet

/**
Expand All @@ -12,34 +14,52 @@ import android.util.AttributeSet

class SquarePinField : PinField{

private var cornerRadius = 0f
set(value) {
field = value
invalidate()
}

private val cursorPadding = Util.dpToPx(5f)

constructor(context: Context): super(context)

constructor(context: Context, attr: AttributeSet) : super(context,attr)
constructor(context: Context, attr: AttributeSet) : super(context,attr){
initParams(attr)
}

constructor(context: Context, attr: AttributeSet, defStyle: Int) : super(context,attr,defStyle)
constructor(context: Context, attr: AttributeSet, defStyle: Int) : super(context,attr,defStyle){
initParams(attr)
}

private fun initParams(attr: AttributeSet){
val a = context.theme.obtainStyledAttributes(attr, R.styleable.SquarePinField, 0,0)
try {
cornerRadius = a.getDimension(R.styleable.SquarePinField_cornerRadius, cornerRadius)
} finally {
a.recycle()
}
}

override fun onDraw(canvas: Canvas?) {

for (i in 0 until numberOfFields){

val x1 = (i*singleFieldWidth)
val padding = (if (distanceInBetween!= defDistanceInBetweenValue) distanceInBetween else getDefaultDistanceInBetween())/2
val padding = (if (distanceInBetween!= DEFAULT_DISTANCE_IN_BETWEEN) distanceInBetween else getDefaultDistanceInBetween())/2
val paddedX1 = (x1 + padding)
val paddedX2 = ((x1+singleFieldWidth)-padding)
val squareHeight = paddedX2-paddedX1
val paddedY1 = (height/2)-(squareHeight/2)
val paddedY2 = (height/2)+(squareHeight/2)
val textX = ((paddedX2-paddedX1)/2)+paddedX1
val textY = ((paddedY2-paddedY1)/2+paddedY1)+ lineThickness +(textPaint.textSize/4)
val character:Char? = text?.getOrNull(i)
val character:Char? = transformationMethod?.getTransformation(text,this)?.getOrNull(i) ?: text.getOrNull(i)

if(isHighlightEnabled && !highlightSingleFieldMode && hasFocus()){
canvas?.drawRect(paddedX1,paddedY1,paddedX2,paddedY2, highlightPaint)
drawRect(canvas,paddedX1,paddedY1,paddedX2,paddedY2, highlightPaint)
}else{
canvas?.drawRect(paddedX1,paddedY1,paddedX2,paddedY2, fieldPaint)
drawRect(canvas,paddedX1,paddedY1,paddedX2,paddedY2, fieldPaint)
}

if(character!=null) {
Expand All @@ -54,9 +74,17 @@ class SquarePinField : PinField{
drawCursor(canvas,textX,cursorY1,cursorY2,highlightPaint)
}
if(isHighlightEnabled && highlightSingleFieldMode){
canvas?.drawRect(paddedX1,paddedY1,paddedX2,paddedY2, highlightPaint)
drawRect(canvas,paddedX1,paddedY1,paddedX2,paddedY2, highlightPaint)
}
}
}
}

private fun drawRect(canvas: Canvas?,paddedX1:Float,paddedY1:Float,paddedX2:Float,paddedY2:Float,paint: Paint){
if(cornerRadius>0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
canvas?.drawRoundRect(paddedX1,paddedY1,paddedX2,paddedY2,cornerRadius,cornerRadius, paint)
}else{
canvas?.drawRect(paddedX1,paddedY1,paddedX2,paddedY2, paint)
}
}
}
8 changes: 8 additions & 0 deletions app/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@
<attr name="highlightSingleFieldMode" format="boolean" />
</declare-styleable>

<declare-styleable name="LinePinField">
<attr name="bottomTextPaddingDp" format="dimension" />
</declare-styleable>

<declare-styleable name="SquarePinField">
<attr name="cornerRadius" format="dimension" />
</declare-styleable>

<declare-styleable name="CirclePinField">
<attr name="circleRadius" format="dimension" />
<attr name="fillerColor" format="color" />
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="accent">#FF4081</color>
<color name="pinFieldLibraryAccent">#FF4081</color>
<color name="inactivePinFieldColor">#808080</color>
<color name="transparent">#00000000</color>
<color name="pinFieldLibraryTransparent">#00000000</color>
</resources>
Loading

0 comments on commit 38da30d

Please sign in to comment.