-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
양 끝에 아이콘을 추가할 수 있는 Edit Text & 검증 텍스트와 텍스트 제한 기능이 있는 Edit Text 구현 #12
Changes from 10 commits
c36922b
00f40ba
84c314b
8a11ff6
f085da7
be6c697
40c1717
9b85710
6d9b401
43ad8d1
cd5b180
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package com.ggne.feature_common.custom | ||
|
||
import android.content.Context | ||
import android.util.AttributeSet | ||
import android.view.LayoutInflater | ||
import androidx.constraintlayout.widget.ConstraintLayout | ||
import com.ggne.feature_common.R | ||
import com.ggne.feature_common.databinding.RoyalFlushIconEditTextBinding | ||
|
||
class RoyalFlushIconEditText(context: Context, attrs: AttributeSet) : | ||
ConstraintLayout(context, attrs) { | ||
|
||
private val binding = | ||
RoyalFlushIconEditTextBinding.inflate(LayoutInflater.from(context), this, true) | ||
|
||
init { | ||
|
||
context.theme.obtainStyledAttributes( | ||
attrs, | ||
R.styleable.RoyalFlushIconEditText, | ||
0, | ||
0, | ||
).apply { | ||
try { | ||
|
||
getResourceId( | ||
R.styleable.RoyalFlushIconEditText_startIcon, | ||
EMPTY_RESOURCE, | ||
).let { resource -> | ||
if (resource == EMPTY_RESOURCE) { | ||
binding.startIc.visibility = GONE | ||
} else { | ||
binding.startIc.setImageResource(resource) | ||
} | ||
} | ||
|
||
getResourceId( | ||
R.styleable.RoyalFlushIconEditText_endIcon, | ||
EMPTY_RESOURCE, | ||
).let { resource -> | ||
if (resource == EMPTY_RESOURCE) { | ||
binding.endIc.visibility = GONE | ||
} else { | ||
binding.endIc.setImageResource(resource) | ||
} | ||
} | ||
|
||
getString(R.styleable.RoyalFlushIconEditText_royalFlushIconEditTextHint).let { hint -> | ||
binding.et.hint = hint | ||
} | ||
} finally { | ||
recycle() | ||
} | ||
} | ||
|
||
removeAllViews() | ||
addView(binding.root) | ||
} | ||
|
||
companion object { | ||
private const val EMPTY_RESOURCE = -1 | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
package com.ggne.feature_common.custom | ||
|
||
import android.content.Context | ||
import android.util.AttributeSet | ||
import android.view.LayoutInflater | ||
import androidx.constraintlayout.widget.ConstraintLayout | ||
import com.ggne.feature_common.extensions.EMPTY | ||
import com.ggne.feature_common.R | ||
import com.ggne.feature_common.extensions.addAfterTextChangedListener | ||
import com.ggne.feature_common.databinding.RoyalFlushVerificationEditTextBinding | ||
|
||
class RoyalFlushVerificationEditText(context: Context, attrs: AttributeSet) : | ||
ConstraintLayout(context, attrs) { | ||
|
||
private var maxLength: Int | ||
private var verificationText: String = String.EMPTY | ||
|
||
val text | ||
get() = binding.et.text.toString() | ||
|
||
val editText | ||
get() = binding.et | ||
|
||
private val binding = | ||
RoyalFlushVerificationEditTextBinding.inflate(LayoutInflater.from(context), this, true) | ||
|
||
init { | ||
|
||
context.theme.obtainStyledAttributes( | ||
attrs, | ||
R.styleable.RoyalFlushVerificationEditText, | ||
0, | ||
0, | ||
).apply { | ||
try { | ||
|
||
getString(R.styleable.RoyalFlushVerificationEditText_royalFlushVerificationEditTextHint).let { hint -> | ||
binding.et.hint = hint | ||
} | ||
|
||
getInt(R.styleable.RoyalFlushVerificationEditText_maxLength, Int.MAX_VALUE).let { inputtedMaxLength -> | ||
maxLength = inputtedMaxLength | ||
} | ||
|
||
getBoolean(R.styleable.RoyalFlushVerificationEditText_isCounterVisible, true).let { isVisible -> | ||
if (isVisible) { | ||
|
||
with(binding.counterTv) { | ||
visibility = VISIBLE | ||
text = context.getString(R.string.text_counter_format, 0, maxLength) | ||
} | ||
|
||
binding.et.addAfterTextChangedListener { text -> | ||
if (text.length <= maxLength) { | ||
binding.counterTv.text = context.getString(R.string.text_counter_format, text.length, maxLength) | ||
} else { | ||
with(binding.et) { | ||
setText(text.substring(0, maxLength)) | ||
setSelection(maxLength) | ||
} | ||
} | ||
} | ||
|
||
} else { | ||
binding.counterTv.visibility = GONE | ||
maxLength = Int.MAX_VALUE | ||
} | ||
|
||
} | ||
|
||
getBoolean(R.styleable.RoyalFlushVerificationEditText_isVerificationVisible, false).let { isVisible -> | ||
if (isVisible) { | ||
getString(R.styleable.RoyalFlushVerificationEditText_verificationText).let { inputtedVerificationText -> | ||
verificationText = inputtedVerificationText ?: String.EMPTY | ||
} | ||
setVerification(true) | ||
} else { | ||
setVerification(false) | ||
} | ||
} | ||
|
||
|
||
} finally { | ||
recycle() | ||
} | ||
} | ||
|
||
removeAllViews() | ||
addView(binding.root) | ||
|
||
} | ||
|
||
fun setVerificationText(text: String) { | ||
verificationText = text | ||
} | ||
|
||
fun setVerification(isVerified: Boolean) { | ||
if (isVerified) { | ||
binding.verificationTv.visibility = VISIBLE | ||
binding.verificationTv.text = verificationText | ||
} else { | ||
binding.verificationTv.visibility = GONE | ||
} | ||
} | ||
|
||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package com.ggne.feature_common.extensions | ||
|
||
val String.Companion.EMPTY: String | ||
get() = "" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package com.ggne.feature_common.extensions | ||
|
||
import android.text.Editable | ||
import android.text.TextWatcher | ||
import android.widget.EditText | ||
|
||
fun EditText.addAfterTextChangedListener(block: (String) -> Unit) { | ||
this.addTextChangedListener(object : TextWatcher { | ||
override fun afterTextChanged(s: Editable?) { | ||
block(s.toString()) | ||
} | ||
|
||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { | ||
} | ||
|
||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { | ||
} | ||
}) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<selector > | ||
<item xmlns:android="http://schemas.android.com/apk/res/android"> | ||
<shape android:shape="rectangle"> | ||
<solid android:color="#DFDBCC" /> | ||
<corners android:radius="8dp" /> | ||
</shape> | ||
</item> | ||
</selector> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
xmlns:app="http://schemas.android.com/apk/res-auto" | ||
xmlns:tools="http://schemas.android.com/tools" | ||
android:layout_width="match_parent" | ||
android:layout_height="60dp" | ||
android:paddingHorizontal="18dp" | ||
android:paddingVertical="14dp" | ||
android:background="@drawable/royal_flush_edit_text_background"> | ||
|
||
<ImageView | ||
android:id="@+id/start_ic" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 어라라 컨벤션이 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아 맞다 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @soopeach 이거 해줘 |
||
android:layout_width="0dp" | ||
android:layout_height="0dp" | ||
android:paddingEnd="4dp" | ||
app:layout_constraintBottom_toBottomOf="@id/et" | ||
app:layout_constraintDimensionRatio="1:1" | ||
app:layout_constraintStart_toStartOf="parent" | ||
app:layout_constraintTop_toTopOf="@id/et" | ||
android:contentDescription="@string/start_ic"/> | ||
|
||
<EditText | ||
android:id="@+id/et" | ||
android:layout_width="0dp" | ||
android:layout_height="0dp" | ||
android:autofillHints="yes" | ||
android:background="@null" | ||
android:gravity="center_vertical" | ||
android:inputType="text" | ||
android:maxLines="1" | ||
android:textSize="18sp" | ||
app:layout_constraintBottom_toBottomOf="parent" | ||
app:layout_constraintEnd_toStartOf="@id/end_ic" | ||
app:layout_constraintStart_toEndOf="@id/start_ic" | ||
app:layout_constraintTop_toTopOf="parent" | ||
tools:ignore="LabelFor" /> | ||
|
||
<ImageView | ||
android:id="@+id/end_ic" | ||
android:layout_width="0dp" | ||
android:layout_height="0dp" | ||
android:paddingStart="4dp" | ||
app:layout_constraintBottom_toBottomOf="@id/et" | ||
app:layout_constraintDimensionRatio="1:1" | ||
app:layout_constraintEnd_toEndOf="parent" | ||
app:layout_constraintTop_toTopOf="@id/et" | ||
android:contentDescription="@string/end_ic"/> | ||
|
||
</androidx.constraintlayout.widget.ConstraintLayout> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ConstraintLayout이 중첩으로 쓰인 이유가 있을까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Linear로 개선이 가능해보이네요 감사합니다! |
||
xmlns:app="http://schemas.android.com/apk/res-auto" | ||
xmlns:tools="http://schemas.android.com/tools" | ||
android:layout_width="match_parent" | ||
android:layout_height="wrap_content"> | ||
|
||
<androidx.constraintlayout.widget.ConstraintLayout | ||
android:id="@+id/et_container" | ||
android:layout_width="match_parent" | ||
android:layout_height="60dp" | ||
android:paddingHorizontal="18dp" | ||
android:paddingVertical="14dp" | ||
app:layout_constraintStart_toStartOf="parent" | ||
app:layout_constraintEnd_toEndOf="parent" | ||
app:layout_constraintTop_toTopOf="parent" | ||
android:background="@drawable/royal_flush_edit_text_background"> | ||
|
||
<EditText | ||
android:id="@+id/et" | ||
android:layout_width="0dp" | ||
android:layout_height="0dp" | ||
android:autofillHints="yes" | ||
android:background="@null" | ||
android:gravity="center_vertical" | ||
android:inputType="text" | ||
android:maxLines="1" | ||
android:textSize="18sp" | ||
app:layout_constraintBottom_toBottomOf="parent" | ||
app:layout_constraintStart_toStartOf="parent" | ||
app:layout_constraintEnd_toStartOf="@id/counter_tv" | ||
app:layout_constraintTop_toTopOf="parent" | ||
tools:ignore="LabelFor" /> | ||
|
||
<TextView | ||
android:id="@+id/counter_tv" | ||
android:layout_width="wrap_content" | ||
android:layout_height="wrap_content" | ||
android:paddingStart="4dp" | ||
app:layout_constraintTop_toTopOf="parent" | ||
app:layout_constraintBottom_toBottomOf="parent" | ||
app:layout_constraintEnd_toEndOf="parent"/> | ||
</androidx.constraintlayout.widget.ConstraintLayout> | ||
|
||
<TextView | ||
android:id="@+id/verification_tv" | ||
android:layout_width="wrap_content" | ||
android:layout_height="wrap_content" | ||
android:layout_marginStart="3dp" | ||
android:layout_marginTop="6dp" | ||
app:layout_constraintStart_toStartOf="parent" | ||
app:layout_constraintTop_toBottomOf="@id/et_container"/> | ||
|
||
</androidx.constraintlayout.widget.ConstraintLayout> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<resources> | ||
<declare-styleable name="RoyalFlushIconEditText"> | ||
<attr name="startIcon" format="reference" /> | ||
<attr name="endIcon" format="reference" /> | ||
<attr name="royalFlushIconEditTextHint" format="string" /> | ||
</declare-styleable> | ||
|
||
<declare-styleable name="RoyalFlushVerificationEditText"> | ||
<attr name="isCounterVisible" format="boolean" /> | ||
<attr name="isVerificationVisible" format="boolean" /> | ||
<attr name="verificationText" format="string" /> | ||
<attr name="maxLength" format="integer" /> | ||
<attr name="royalFlushVerificationEditTextHint" format="string" /> | ||
</declare-styleable> | ||
</resources> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<resources> | ||
<string name="start_ic">시작 아이콘</string> | ||
<string name="end_ic">끝 아이콘</string> | ||
<string name="text_counter_format">%d/%d</string> | ||
<string name="can_use_nickname">사용 가능한 닉네임입니다.</string> | ||
</resources> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이런 리소스에 있는 hex color도 테마에 미리 정해놓은걸로 쓸수있나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
그럼요