Skip to content

Commit a511eda

Browse files
author
Justin Kirk
committed
#185 Add new properties for FormImageElement. Update doc XML for AndroidX.
1 parent dc4046c commit a511eda

12 files changed

Lines changed: 149 additions & 96 deletions

File tree

app/src/main/java/com/thejuki/kformmasterexample/FullscreenFormActivity.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,11 @@ class FullscreenFormActivity : AppCompatActivity() {
202202
displayDivider = false
203203
imageTransformation = CircleTransform(borderColor = Color.WHITE, borderRadius = 3) //Default value for this is CircleTransform(null) so it makes image round without borders
204204
required = false
205+
enabled = true
206+
showChangeImageLabel = true
207+
changeImageLabel = "Change me"
208+
displayImageHeight = 200
209+
displayImageWidth = 200
205210
theme = R.style.CustomDialogPicker // This is to theme the default dialog when onClickListener is not used.
206211
//defaultImage = R.drawable.default_image
207212
//value = "https://via.placeholder.com/200" //(String) This needs to be an image URL, data URL, or an image FILE (absolutePath)

app/src/main/java/com/thejuki/kformmasterexample/custom/view/FormCustomViewBinder.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import com.thejuki.kformmasterexample.custom.state.FormCustomViewState
2525
* @author **TheJuki** ([GitHub](https://github.com/TheJuki))
2626
* @version 1.0
2727
*/
28-
class CustomViewBinder(private val context: Context, private val formBuilder: FormBuildHelper, @LayoutRes private val layoutID: Int?) : BaseFormViewBinder() {
28+
class CustomViewBinder(private val context: Context, private val formBuilder: FormBuildHelper, @LayoutRes private val layoutID: Int? = null) : BaseFormViewBinder() {
2929
var viewBinder = ViewBinder(layoutID
3030
?: R.layout.form_element_custom, FormCustomElement::class.java, { model, finder, _ ->
3131
val textViewTitle = finder.find(R.id.formElementTitle) as AppCompatTextView

app/src/main/res/layout/activity_fullscreen_form.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<?xml version="1.0" encoding="utf-8"?>
12
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
23
android:layout_width="match_parent"
34
android:layout_height="match_parent"

docs/custom/element.md

Lines changed: 33 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -10,35 +10,37 @@ Create a new XML layout file. We'll name it form_element_custom.xml.
1010
xmlns:tools="http://schemas.android.com/tools"
1111
android:layout_width="match_parent"
1212
android:layout_height="wrap_content"
13-
android:background="@android:color/black"
13+
android:background="@color/colorFormMasterElementBackground"
1414
android:orientation="vertical"
1515
android:paddingBottom="16dp">
1616

1717
<View
18+
android:id="@+id/formElementDivider"
1819
android:layout_width="match_parent"
1920
android:layout_height="0.5dp"
2021
android:layout_marginLeft="16dp"
2122
android:layout_marginRight="16dp"
2223
android:background="@color/colorFormMasterDivider" />
2324

2425
<LinearLayout
26+
android:id="@+id/formElementMainLayout"
2527
android:layout_width="match_parent"
2628
android:layout_height="wrap_content"
2729
android:layout_marginLeft="16dp"
2830
android:layout_marginRight="16dp"
2931
android:layout_marginTop="16dp"
3032
android:orientation="horizontal">
3133

32-
<android.support.v7.widget.AppCompatTextView
34+
<com.thejuki.kformmaster.widget.IconTextView
3335
android:id="@+id/formElementTitle"
3436
android:layout_width="0dp"
3537
android:layout_height="wrap_content"
3638
android:layout_weight="2"
37-
android:textColor="@android:color/white"
39+
android:textColor="@color/colorFormMasterElementTextTitle"
3840
android:textSize="@dimen/elementTextTitleSize"
39-
tools:text="Test Title" />
41+
tools:text="Custom Title" />
4042

41-
<android.support.v7.widget.AppCompatEditText
43+
<com.thejuki.kformmaster.widget.ClearableEditText
4244
android:id="@+id/formElementValue"
4345
android:layout_width="0dp"
4446
android:layout_height="wrap_content"
@@ -48,13 +50,14 @@ Create a new XML layout file. We'll name it form_element_custom.xml.
4850
android:imeOptions="actionNext"
4951
android:inputType="textNoSuggestions"
5052
android:maxLines="1"
51-
android:textColor="@color/colorFormMasterElementFocusedTitle"
52-
android:textSize="20sp"
53-
tools:text="Test Value" />
53+
android:textColor="@drawable/edit_text_selector"
54+
android:textColorHint="@color/colorFormMasterElementHint"
55+
android:textSize="@dimen/elementTextValueSize"
56+
tools:text="Custom Value" />
5457

5558
</LinearLayout>
5659

57-
<android.support.v7.widget.AppCompatTextView
60+
<androidx.appcompat.widget.AppCompatTextView
5861
android:id="@+id/formElementError"
5962
android:layout_width="match_parent"
6063
android:layout_height="0dp"
@@ -65,7 +68,7 @@ Create a new XML layout file. We'll name it form_element_custom.xml.
6568
android:textColor="@color/colorFormMasterElementErrorTitle"
6669
android:textSize="@dimen/elementErrorTitleSize"
6770
android:visibility="gone"
68-
tools:text="Test Error" />
71+
tools:text="Personal Info" />
6972

7073
</LinearLayout>
7174
```
@@ -75,39 +78,17 @@ Create a new XML layout file. We'll name it form_element_custom.xml.
7578
Note that a new model does not need to contain a body if BaseFormElement provides everything you need.
7679

7780
```kotlin
78-
class FormCustomElement: BaseFormElement<String> {
79-
constructor() : super()
80-
constructor(tag: Int) : super(tag)
81-
}
81+
class FormCustomElement(tag: Int = -1) : BaseFormElement<String>(tag)
8282
```
8383

8484
### Optional: Form Builder Extension
8585

86-
Create a FormBuildHelper DSL method and builder class for your custom form model.
86+
Create a FormBuildHelper DSL method for your custom form model.
8787

8888
```kotlin
89-
/** Builder method to add a CustomElement */
90-
class CustomElementBuilder(tag: Int = -1) : BaseElementBuilder<String>(tag) {
91-
override fun build() =
92-
FormCustomElement(tag).apply {
93-
this@CustomElementBuilder.let {
94-
title = it.title.orEmpty()
95-
value = it.value
96-
hint = it.hint
97-
rightToLeft = it.rightToLeft
98-
maxLines = it.maxLines
99-
error = it.error
100-
required = it.required
101-
enabled = it.enabled
102-
visible = it.visible
103-
valueObservers.addAll(it.valueObservers)
104-
}
105-
}
106-
}
107-
10889
/** FormBuildHelper extension to add a CustomElement */
109-
fun FormBuildHelper.customEx(tag: Int = -1, init: CustomElementBuilder.() -> Unit): FormCustomElement {
110-
return addFormElement(CustomElementBuilder(tag).apply(init))
90+
fun FormBuildHelper.customEx(tag: Int = -1, init: FormCustomElement.() -> Unit): FormCustomElement {
91+
return addFormElement(FormCustomElement(tag).apply(init))
11192
}
11293
```
11394

@@ -146,59 +127,38 @@ Create a view binder for your custom form element.
146127
* viewStateProvider parameter - Form element view state provider
147128

148129
```kotlin
149-
class CustomViewBinder(private val context: Context,
150-
private val formBuilder: FormBuildHelper) : BaseFormViewBinder() {
151-
var viewBinder = ViewBinder(R.layout.form_element_custom,
152-
FormCustomElement::class.java, { model, finder, _ ->
130+
class CustomViewBinder(private val context: Context, private val formBuilder: FormBuildHelper,
131+
@LayoutRes private val layoutID: Int?) : BaseFormViewBinder() {
132+
var viewBinder = ViewBinder(layoutID
133+
?: R.layout.form_element_custom, FormCustomElement::class.java, { model, finder, _ ->
153134
val textViewTitle = finder.find(R.id.formElementTitle) as AppCompatTextView
154135
val mainViewLayout = finder.find(R.id.formElementMainLayout) as? LinearLayout
155136
val textViewError = finder.find(R.id.formElementError) as AppCompatTextView
137+
val dividerView = finder.find(R.id.formElementDivider) as? View
156138
val itemView = finder.getRootView() as View
157-
val editTextValue = finder.find(R.id.formElementValue) as AppCompatEditText
158-
baseSetup(model, textViewTitle, textViewError, itemView, mainViewLayout, editTextValue)
139+
val editTextValue = finder.find(R.id.formElementValue) as com.thejuki.kformmaster.widget.ClearableEditText
140+
baseSetup(model, dividerView, textViewTitle, textViewError, itemView, mainViewLayout, editTextValue)
159141

160142
editTextValue.setText(model.valueAsString)
161143
editTextValue.hint = model.hint ?: ""
162144

163-
setEditTextFocusEnabled(editTextValue, itemView)
164-
165-
editTextValue.setOnFocusChangeListener { _, hasFocus ->
166-
if (hasFocus) {
167-
textViewTitle.setTextColor(ContextCompat.getColor(context,
168-
R.color.colorFormMasterElementFocusedTitle))
169-
} else {
170-
textViewTitle.setTextColor(ContextCompat.getColor(context,
171-
R.color.colorFormMasterElementTextTitle))
172-
}
173-
}
174-
175145
// Initially use 4 lines
176146
// unless a different number was provided
177147
if (model.maxLines == 1) {
178148
model.maxLines = 4
179149
}
180150

181-
editTextValue.addTextChangedListener(object : TextWatcher {
182-
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i2: Int, i3: Int) {}
151+
// If an InputType is provided, use it instead
152+
model.inputType?.let { editTextValue.setRawInputType(it) }
183153

184-
override fun onTextChanged(charSequence: CharSequence, i: Int, i2: Int, i3: Int) {
154+
// If imeOptions are provided, use them instead of creating a new line
155+
model.imeOptions?.let { editTextValue.imeOptions = it }
185156

186-
// get current form element, existing value and new value
187-
val currentValue = model.valueAsString
188-
val newValue = charSequence.toString()
189-
190-
// trigger event only if the value is changed
191-
if (currentValue != newValue) {
192-
// NOTE: Use setValue()
193-
// as this will suppress the unchecked cast
194-
model.setValue(newValue)
195-
model.error = null
196-
formBuilder.onValueChanged(model)
197-
}
198-
}
157+
setEditTextFocusEnabled(editTextValue, itemView)
158+
setOnFocusChangeListener(context, model, formBuilder)
159+
addTextChangedListener(model, formBuilder)
160+
setOnEditorActionListener(model, formBuilder)
199161

200-
override fun afterTextChanged(editable: Editable) {}
201-
})
202162
}, object : ViewStateProvider<FormCustomElement, ViewHolder> {
203163
override fun createViewStateID(model: FormCustomElement): Int {
204164
return model.id
@@ -213,7 +173,7 @@ private val formBuilder: FormBuildHelper) : BaseFormViewBinder() {
213173
itemView.setOnClickListener {
214174
editTextValue.requestFocus()
215175
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
216-
editTextValue.setSelection(editTextValue.text.length)
176+
editTextValue.setSelection(editTextValue.text?.length ?: 0)
217177
imm.showSoftInput(editTextValue, InputMethodManager.SHOW_IMPLICIT)
218178
}
219179
}

docs/element/imageView.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ imageView(1) {
1313
displayDivider = false
1414
imageTransformation = CircleTransform(borderColor = Color.WHITE, borderRadius = 3)
1515
required = false
16+
showChangeImageLabel = true
17+
changeImageLabel = "Change me"
18+
displayImageHeight = 200
19+
displayImageWidth = 200
1620
theme = R.style.CustomDialogPicker
1721
defaultImage = R.drawable.default_image
1822
value = "http://example.com/"

docs/index.md

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,13 @@ implementation "com.thejuki:k-form-master:$kFormMasterVersion"
1313

1414
```xml
1515
<?xml version="1.0" encoding="utf-8"?>
16-
<LinearLayout
17-
xmlns:android="http://schemas.android.com/apk/res/android"
18-
xmlns:tools="http://schemas.android.com/tools"
16+
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
1917
android:layout_width="match_parent"
2018
android:layout_height="match_parent"
21-
android:orientation="vertical">
22-
23-
<android.support.v7.widget.RecyclerView
24-
android:layout_width="match_parent"
25-
android:layout_height="match_parent"
26-
android:orientation="vertical"
27-
android:id="@+id/recyclerView"
28-
android:descendantFocusability="beforeDescendants" />
29-
30-
</LinearLayout>
19+
android:orientation="vertical"
20+
android:id="@+id/recyclerView"
21+
android:divider="#b5b5b5"
22+
android:descendantFocusability="beforeDescendants" />
3123
```
3224

3325
* Step 2 (No DSL). Add the Form Elements programmatically in your activity

form/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ apply plugin: 'kotlin-android-extensions'
44
apply plugin: "guru.stefma.bintrayrelease"
55
apply plugin: 'jacoco'
66

7-
version = '6.5.2'
7+
version = '6.5.3'
88

99
android {
1010
compileSdkVersion 29
1111

1212
defaultConfig {
1313
minSdkVersion 19
1414
targetSdkVersion 29
15-
versionCode 46
15+
versionCode 47
1616
versionName project.version
1717
multiDexEnabled true
1818
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

form/src/main/java/com/thejuki/kformmaster/extensions/Int+Pixel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ import android.util.TypedValue
1818
fun Int?.dpToPx(): Int {
1919
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
2020
this?.toFloat() ?: 0f, Resources.getSystem().displayMetrics).toInt()
21-
}
21+
}

form/src/main/java/com/thejuki/kformmaster/model/FormImageElement.kt

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ import android.util.Base64
88
import android.view.View
99
import android.webkit.URLUtil
1010
import android.widget.ImageView
11+
import androidx.appcompat.widget.AppCompatTextView
1112
import androidx.core.content.ContextCompat
1213
import com.caverock.androidsvg.SVG
1314
import com.github.dhaval2404.imagepicker.constant.ImageProvider
1415
import com.squareup.picasso.Transformation
1516
import com.thejuki.kformmaster.R
17+
import com.thejuki.kformmaster.extensions.dpToPx
1618
import com.thejuki.kformmaster.extensions.setImage
1719
import com.thejuki.kformmaster.helper.CircleTransform
1820
import com.thejuki.kformmaster.helper.ImagePickerOptions
@@ -29,6 +31,20 @@ import java.nio.charset.Charset
2931
*/
3032
class FormImageElement(tag: Int = -1) : BaseFormElement<String>(tag) {
3133

34+
/**
35+
* Change Image Label View
36+
*/
37+
var changeImageLabelView: AppCompatTextView? = null
38+
set(value) {
39+
field = value
40+
changeImageLabelView?.let {
41+
it.visibility = if (!showChangeImageLabel) View.GONE else View.VISIBLE
42+
if (changeImageLabel != null) {
43+
it.text = changeImageLabel
44+
}
45+
}
46+
}
47+
3248
/**
3349
* Unit called when an image is selected. A File object is returned.
3450
*/
@@ -54,6 +70,68 @@ class FormImageElement(tag: Int = -1) : BaseFormElement<String>(tag) {
5470
*/
5571
var defaultImage: Int? = null
5672

73+
/**
74+
* Display Image Width in DP
75+
* (optional - uses @dimen/elementImageDisplayWidth)
76+
*/
77+
var displayImageWidth: Int? = null
78+
set(value) {
79+
field = value
80+
81+
if (value != null) {
82+
editView?.let {
83+
if (it is ImageView) {
84+
val imageViewLayoutParams = it.layoutParams
85+
imageViewLayoutParams.width = value.dpToPx()
86+
it.layoutParams = imageViewLayoutParams
87+
}
88+
}
89+
}
90+
}
91+
92+
/**
93+
* Display Image Height in DP
94+
* (optional - uses @dimen/elementImageDisplayHeight)
95+
*/
96+
var displayImageHeight: Int? = null
97+
set(value) {
98+
field = value
99+
if (value != null) {
100+
editView?.let {
101+
if (it is ImageView) {
102+
val imageViewLayoutParams = it.layoutParams
103+
imageViewLayoutParams.height = value.dpToPx()
104+
it.layoutParams = imageViewLayoutParams
105+
}
106+
}
107+
}
108+
}
109+
110+
/**
111+
* Change Image Label
112+
* (optional - uses R.string.form_master_picker_change_image)
113+
*/
114+
var changeImageLabel: String? = null
115+
set(value) {
116+
field = value
117+
changeImageLabelView?.let {
118+
it.visibility = if (!showChangeImageLabel) View.GONE else View.VISIBLE
119+
it.text = changeImageLabel
120+
}
121+
}
122+
123+
/**
124+
* Show the Change Image Label
125+
* By default, this is true.
126+
*/
127+
var showChangeImageLabel: Boolean = true
128+
set(value) {
129+
field = value
130+
changeImageLabelView?.let {
131+
it.visibility = if (!showChangeImageLabel) View.GONE else View.VISIBLE
132+
}
133+
}
134+
57135
/**
58136
* The Picasso Image Transformation.
59137
* By default this is [CircleTransform].

0 commit comments

Comments
 (0)