8000 GitHub - TheJuki/KFormMaster at 3.0.0
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

TheJuki/KFormMaster

Repository files navigation

KFormMaster: Generic form builder in Kotlin

Build status codecov codebeat badge API Android Arsenal Download

This is a Kotlin port of FormMaster

Examples

Full Screen Partial Screen Login
Example Example Example

This library aids in building bigger forms on-the-fly. Forms with large number of elements can easily be added programmatically within a few minutes.

Features

  • Easily build big and bigger forms with minimal effort
  • Fast color change as needed
  • Kotlin port of FormMaster

Version 3 Changes

  • The title, edit, and error views are now accessible through the model classes
  • The refreshView() function has been removed (No longer needed)
  • The getFormElement() function now requires a type and returns a non-optional element
  • The form is now dynamic. The title, hint, value, error, visible, required fields can be changed at any time without refreshing the form manually.
  • The clear() function has been added to all form elements
  • The header can now collapse "child" elements when tapped (Set collapsible to true)
  • The FullscreenFormActivity example has been updated to test the new dynamic features

Java Compatibility

  • This library was ported from Java and is still compatibile with Java code
  • See Java Example

Installation

Add this in your app's build.gradle file:

ext {
  kFormMasterVersion = '3.0.0'
}

implementation "com.thejuki:k-form-master:$kFormMasterVersion"

How to use

  • Step 1. Add a Recyclerview anywhere in the layout where you want your list to be shown (If confused, look at the examples in this repo).
<?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:orientation="vertical">

    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:id="@+id/recyclerView"
        android:descendantFocusability="beforeDescendants" />

</LinearLayout>
  • Step 2 (No DSL). Add the Form Elements programmatically in your activity
// Initialize variables
formBuilder = FormBuildHelper(this)
formBuilder.attachRecyclerView(this, recyclerView)

val elements: MutableList<BaseFormElement<*>> = mutableListOf()

// Declare form elements
val emailElement = FormEmailEditTextElement(Email.ordinal)
        .setTitle(getString(R.string.email))
elements.add(emailElement)

val passwordElement = FormPasswordEditTextElement(Password.ordinal)
        .setTitle(getString(R.string.password))
elements.add(passwordElement)

// Add form elements (Form is refreshed for you)
formBuilder.addFormElements(elements)
  • Step 2 (With DSL). Add the Form Elements programmatically in your activity
formBuilder = form(this, recyclerView) {
    email(Email.ordinal) {
        title = getString(R.string.email)
    }
    password(Password.ordinal) {
        title = getString(R.string.password)
    }
}

Reference

Item Definition

Header:

val header = FormHeader.createInstance(getString(R.string.HeaderString))

Regular Elements:

General object format

val element = Form[Type]Element<T: Serializable>(TAG_NAME: Int) // Tag is optional. It is recommended to use an Enum's ordinal.
    .setTitle("Pick your favourite fruit") // setting title
    .setValue("Banana") // setting value of the field, if any
    .setOptions(fruits) // setting pickable options, if any
    .setHint("e.g. banana, guava etc") // setting hints, if any
    .setRequired(false) // marking if the form element is required to be filled to make the form valid, include if needed

Samples:

// Example Enum
private enum class Tag {
    Email,
    Phone,
    Location,
    Address,
    ZipCode,
    Date,
    Time,
    DateTime,
    Password,
    SingleItem,
    MultiItems,
    AutoCompleteElement,
    AutoCompleteTokenElement,
    ButtonElement,
    TextViewElement,
    SwitchElement,
    SliderElement,
    CheckBoxElement,
}

// Example Picker object
import java.io.Serializable

data class ListItem(val id: Long? = null,
                    val name: String? = null
): Serializable {
    override fun toString(): String {
        return name.orEmpty()
    }
}

// Example Autocomplete object
import java.io.Serializable

data class ContactItem(val id: Long? = null,
                       val value: String? = null,
                       val label: String? = null
): Serializable {
    override fun toString(): String {
        return label.orEmpty()
    }
}

val listener = object : OnFormElementValueChangedListener {
    override fun onValueChanged(formElement: BaseFormElement<*>) {

    }
}

formBuilder = form(this@ActivityName, recyclerView, listener, cacheForm = true) {

    // Header
    header { title = getString(R.string.PersonalInfo) }

    // Email EditText
    email(Email.ordinal) {
        title = getString(R.string.email)
        hint = getString(R.string.email_hint)
    }

    // Password EditText
    password(Password.ordinal) {
        title = getString(R.string.password)
    }

    // Phone EditText
    phone(Phone.ordinal) {
        title = getString(R.string.Phone)
        value = "+8801712345678"
    }

    // Singleline text EditText
    text(Location.ordinal) {
        title = getString(R.string.Location)
        value = "Dhaka"
    }

    // Multiline EditText
    textArea(Address.ordinal) {
        title = getString(R.string.Address)
        value = ""
    }

    // Number EditText
    number(ZipCode.ordinal) {
        title = getString(R.string.ZipCode)
        value = "1000"
    }

    // Date
    date(Tag.Date.ordinal) {
        title = getString(R.string.Date)
        dateValue = Date()
        dateFormat = SimpleDateFormat("MM/dd/yyyy", Locale.US)
    }

    // Time
    time(Time.ordinal) {
        title = getString(R.string.Time)
        dateValue = Date()
        dateFormat = SimpleDateFormat("hh:mm a", Locale.US)
    }

    // DateTime
    dateTime(DateTime.ordinal) {
        title = getString(R.string.DateTime)
        dateValue = Date()
        dateFormat = SimpleDateFormat("MM/dd/yyyy hh:mm a", Locale.US)
    }

    // DropDown
    dropDown<ListItem>(SingleItem.ordinal) {
        title = getString(R.string.SingleItem)
        dialogTitle = getString(R.string.SingleItem)
        options = fruits
        value = ListItem(id = 1, name = "Banana")
    }

    // MultiCheckBox
    multiCheckBox<ListItem>(MultiItems.ordinal) {
        title = getString(R.string.MultiItems)
        dialogTitle = getString(R.string.MultiItems)
        options = fruits
        optionsSelected = listOf(ListItem(id = 1, name = "Banana"))
    }

    // AutoComplete
    autoComplete<ContactItem>(AutoCompleteElement.ordinal) {
        title = getString(R.string.AutoComplete)
        arrayAdapter = ContactAutoCompleteAdapter(this@FormListenerActivity,
                android.R.layout.simple_list_item_1, defaultItems =
        arrayListOf(ContactItem(id = 1, value = "", label = "Try \"Apple May\"")))
        dropdownWidth = ViewGroup.LayoutParams.MATCH_PARENT
        value = ContactItem(id = 1, value = "John Smith", label = "John Smith (Tester)")
    }

    // AutoCompleteToken
    autoCompleteToken<ArrayList<ContactItem>>(AutoCompleteTokenElement.ordinal) {
        title = getString(R.string.AutoCompleteToken)
        arrayAdapter = EmailAutoCompleteAdapter(this@FormListenerActivity,
                android.R.layout.simple_list_item_1)
        dropdownWidth = ViewGroup.LayoutParams.MATCH_PARENT
    }

    // Text View
    textView(TextViewElement.ordinal) {
        title = getString(R.string.TextView)
        value = "This is readonly!"
    }

    // Switch
    switch<String>(SwitchElement.ordinal) {
        title = getString(R.string.Switch)
        value = "Yes"
        onValue = "Yes"
        offValue = "No"
    }

    // Slider
    slider(SliderElement.ordinal) {
        title = getString(R.string.Slider)
        value = 50
        min = 0
        max = 100
        steps = 20
    }

    // CheckBox
    checkBox<Boolean>(CheckBoxElement.ordinal) {
        title = getString(R.string.CheckBox)
        value = true
        checkedValue = true
        unCheckedValue = false
    }

    // Button
    button(ButtonElement.ordinal) {
        value = getString(R.string.Button)
        valueObservers.add({ newValue, element ->
            val confirmAlert = AlertDialog.Builder(this@PartialScreenFormActivity).create()
            confirmAlert.setTitle(this@PartialScreenFormActivity.getString(R.string.Confirm))
            confirmAlert.setButton(AlertDialog.BUTTON_POSITIVE, this@PartialScreenFormActivity.getString(android.R.string.ok), { _, _ ->
                // Could be used to clear another field:
                val dateToDeleteElement = formBuilder.getFormElement<FormPickerDateElement>(Tag.Date.ordinal)
                // Display current date
                Toast.makeText(this@FullscreenFormActivity,
                        dateToDeleteElement.value?.getTime().toString(),
                        Toast.LENGTH_SHORT).show()
                dateToDeleteElement.clear()
                formBuilder.onValueChanged(dateToDeleteElement)
            })
            confirmAlert.setButton(AlertDialog.BUTTON_NEGATIVE, this@PartialScreenFormActivity.getString(android.R.string.cancel), { _, _ ->
            })
            confirmAlert.show()
        })
    }
}

Cache Form Elements

By default, RecyclerView will cache 2 views. By setting cacheForm = true in the FormBuildHelper, all form elements will be cached instead of recycled. Set this if you have a small form.

Set form element value change listener to get changed value instantly

While creating a new instance of FormBuildHelper, add a listener in the constructor

var formBuilder = FormBuildHelper(this, object : OnFormElementValueChangedListener {
    override fun onValueChanged(formElement: BaseFormElement<*>) {
         // do anything here with formElement.value
    }
}, findViewById(R.id.recyclerView), cacheForm = true)

Get value for unique form elements

Use the unique tag assigned earlier to retrieve value (See examples in this repo)

val element = formBuilder!!.getFormElement(Email.ordinal)
val value: String = element?.value as String

Use the added index of the element instead if you did not assign a tag.

val element = formBuilder!!.getElementAtIndex(2)
val value: String = element?.value as String

Check if form is valid

Use this variable (method in Java) if you need to check whether the required elements of the form are completed

formBuilder.isValidForm // returns Boolean whether the form is valid or not

Form accent color change

If you want to change the colors, just override the colors in your colors.xml file:

<color name="colorFormMasterHeaderBackground">#DDDDDD</color>
<color name="colorFormMasterHeaderText">#000000</color>
<color name="colorFormMasterElementBackground">#FFFFFF</color>
<color name="colorFormMasterElementTextTitle">#222222</color>
<color name="colorFormMasterElementErrorTitle">#FF0000</color>
<color name="colorFormMasterElementTextValue">#000000</color>
<color name="colorFormMasterElementButtonText">#42A5F5</color>
<color name="colorFormMasterElementFocusedTitle">#0277bd</color>
<color name="colorFormMasterElementTextDisabled">#757575</color>
<color name="colorFormMasterDivider">#DDDDDD</color>
<color name="colorFormMasterElementToken">#f5f5f5</color>

Form UI change

If you want to change how the forms look, just override a form_element XML in your project.

Just make sure to keep the ID name the same as it is in the library for the components.

android:id="@+id/formElementTitle"
android:id="@+id/formElementValue"
...

Contributing

You can contribute to the original Java library here: FormMaster OR You can submit pull requests or issues to this project to make this port even better!

Credits

BrowserStack

BrowserStack

The App Automate feature of BrowserStack is used for Espresso testing of this library. The App Automate REST API is used to upload the example app and test app to test multiple devices in parallel.

License

The library is available as open source under the terms of the Apache License, Version 2.0.

About

Generic form builder in Kotlin

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Contributors 11

0