QMBForm

Travis-CI Coverage Technical Dept

Create simple Android forms

Demo

Basic Usage

  1. Create a "FromDescriptor" - It's the holder for the form

    FormDescriptor descriptor = FormDescriptor.newInstance();
    descriptor.setOnFormRowValueChangedListener(this); //Listen for changes
  2. Create sections with "SectionDescriptor" and add rows - Sections can have titles and rows (Form Elements)

    SectionDescriptor sectionDescriptor = SectionDescriptor.newInstance("tag","Title");
    
    //Add rows - form elements
    sectionDescriptor.addRow( RowDescriptor.newInstance("text",RowDescriptor.FormRowDescriptorTypeText, "Text", new Value<String>("test")) );
    sectionDescriptor.addRow( RowDescriptor.newInstance("dateDialog",RowDescriptor.FormRowDescriptorTypeDate, "Date Dialog") );
  3. To render your form, use the "FormManager" helper. You will need a ListView instance.

        FormManager formManager = new FormManager();
        formManager.setup(descriptor, mListView, getActivity());
        formManager.setOnFormRowClickListener(this);    
  4. Attention! If you use EditText based form elements, make sure you set "windowSoftInputMode" to "adjustPan"

    Do it in your manifest:

    <activity
                  android:windowSoftInputMode="adjustPan"/>
    

    Or programmatically in the onCreate method of your activity

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
        super.onCreate(savedInstanceState);
    
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
    
    }
  5. Create elements with custom type identifier and a FormCell class. You can also submit configs to use objects in your cell

    String customType = "customRowIdentifier";
    CellViewFactory.getInstance().setRowTypeMap(customType, CustomFormCell.class);
    
    RowDescriptor customRow = RowDescriptor.newInstance("custom",customType, "title", new Value<String>("value"));
    HashMap<String, Object> cellConfig = new HashMap();
    cellConfig.put("config",configObject);
    customRow.setCellConfig(cellConfig);
    section.addRow(customRow);

Use annotations for models

  1. You can create a form from a POJO by adding annotations to your model properties

    public class Entry {
    
        @FormElement(
                label = R.string.lb_title,
                rowDescriptorType = RowDescriptor.FormRowDescriptorTypeText,
                sortId = 1,
                section = R.string.section_general
        )
        public String title;
    
        @FormElement(
                label = R.string.lb_description,
                rowDescriptorType = RowDescriptor.FormRowDescriptorTypeTextView,
                sortId = 2,
                section = R.string.section_general
        )
        public String description;
    
        @FormElement(
                label = R.string.lb_date_dialog,
                rowDescriptorType = RowDescriptor.FormRowDescriptorTypeDate,
                sortId = 4,
                section = R.string.section_date
        )
        public Date date;
    
        @FormElement(
                label = R.string.lb_date_inline,
                rowDescriptorType = RowDescriptor.FormRowDescriptorTypeDateInline,
                tag = "customDateInlineTag",
                sortId = 3,
                section = R.string.section_date
        )
        public Date dateInline;
    
    }
    
  2. Use "FormDescriptorAnnotationFactory" to create a FormDescriptor from your model

    FormDescriptorAnnotationFactory factory = new FormDescriptorAnnotationFactory(getActivity());
    FormDescriptor descriptor = factory.createFormDescriptorFromAnnotatedClass(entry);

Validation

  1. Define custom validators by implementing FormValidator

    public class EmailValidator implements FormValidator {
        private static final String EMAIL_PATTERN =
                "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@"
                        + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
    
        @Override
        public RowValidationError validate(RowDescriptor descriptor) {
            Value value = descriptor.getValue();
            if (value.getValue() != null && value.getValue() instanceof String) {
                String val = (String) value.getValue();
                return (val.matches(EMAIL_PATTERN)) ? null : new RowValidationError(descriptor,  R.string.validation_invalid_email);
            }
            return new RowValidationError(descriptor, R.string.validation_invalid_email);
        }
    }
  2. With annotations Specify validator classes as an array of .class items

    @FormElement(
            label = R.string.email,
            rowDescriptorType = RowDescriptor.FormRowDescriptorTypeEmailInline,
            sortId = 2,
            validatorClasses = {EmailValidator.class, BlankStringValidator.class}
    )
    public String email;
  3. Or add validators to rowdescriptors manually

    RowDescriptor rowDescriptor = RowDescriptor.newInstance("valid",
        RowDescriptor.FormRowDescriptorTypeEmail,
        "Email Test",
        new Value<String>("notavalidemail"));
    
    rowDescriptor.addValidator(new EmailValidator());

Installation

QMBForm is not available at the maven repository yet. But it's a gradly based android-library project.

  1. Include the QMBFrom directory as a library module in your application
  2. see sample application:

Add this to your build.gradle dependencies section

  compile project(":lib:QMBForm")

Add this to your settings.gradle

  include ':app', ':lib:QMBForm'

QMBForm has no dependencies to other third party libs (but compile 'com.android.support:appcompat-v7:19.+') is needed

Supported Form Elements

Most elements have an inline version (label on the same line as the displayed value) and a normal version (label on separate line above displayed value).

To do

Credits

QMBForm is based on the ideas of XLForm - the most flexible and powerful iOS library to create dynamic table-view forms.

Thanks guys!