Skip to content
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

How do I use Epoxy to create forms? #426

Open
ColtonIdle opened this issue Apr 24, 2018 · 8 comments

Comments

Projects
None yet
8 participants
@ColtonIdle
Copy link

commented Apr 24, 2018

Our team has been using Epoxy now for a few months, but noticed that you can also use it for static content. We first want to address our Login page. It's currently a scrollView with a linear layout, with an imageView, and a few editTexts and a button. How do I use Epoxy for a screen where I would typically be able to directly access all of the views? I didn't see any real docs/wiki surrounding this. Sorry if I missed it.

@elihart

This comment has been minimized.

Copy link
Contributor

commented Apr 24, 2018

The quick answer is that you need to register a text watcher on the model and save the text value to a field whenever it changes. Rebuilding models should rely on that field to set the data. Models should also be rebuilt whenever the field is updated, but it is recommend to use requestDelayedModelBuild to avoid rebuilding on every character input.

Since models need to be rebuilt there is a surprisingly tricky issue with the cursor maintaining the correct position. Our app has a lot of pages with forms that we use Epoxy with, and it took us a while to get it right, but I created some utils to help and we have a pretty good pattern now.

I am leaving on a trip today, but I will try to share sample code and more details soon. It's something I've been meaning to do for a while because it isn't too straightforward and has some gotchas to it.

#218 is slightly related and you could read through that for some details

@ngsilverman ngsilverman added the question label May 1, 2018

@yesez5

This comment has been minimized.

Copy link

commented May 25, 2018

Hi @elihart .. we really need those utils 😄 We want to build something like Eureka (a library for iOS) but for Android. We would appreciate your help.

@elihart

This comment has been minimized.

Copy link
Contributor

commented May 29, 2018

@yesez5 Sorry for the delay, things have been busy. That's great that you want to work on an Android version of Eureka though!

Here is the pattern we use, it's pretty straightforward. This doesn't include the part of the code that handles the TextWatcher and callback to rebuild models, if you are confused about that part let me know and I can provide another snipped.

I still mean to provide an official wiki entry and sample for this, but hopefully I can unblock you in the meantime

@TextProp
    public void setInputText(@Nullable CharSequence text) {
        if (setText(editText, text)) {
            // If the text changed then we move the cursor to the end of the new text. This allows us to fill in text programmatically if needed,
            // like a search suggestion, but if the user is typing and the view is rebound we won't lose their cursor position.
            editText.setSelection(editText.length());
        }
    }

    public static boolean setText(TextView textView, @Nullable CharSequence text) {
        if (!isTextDifferent(text, textView.getText())) {
            // Previous text is the same. No op
            return false;
        }


        textView.setText(text);

        return true;
    }

    /**
     * @return True if str1 is different from str2.
     * <p>
     * This is adapted from how the Android DataBinding library binds its text views.
     */
    public static boolean isTextDifferent(@Nullable CharSequence str1, @Nullable CharSequence str2) {
        if (str1 == str2) {
            return false;
        }
        if ((str1 == null) || (str2 == null)) {
            return true;
        }
        final int length = str1.length();
        if (length != str2.length()) {
            return true;
        }

        if (str1 instanceof Spanned) {
            return !str1.equals(str2);
        }

        for (int i = 0; i < length; i++) {
            if (str1.charAt(i) != str2.charAt(i)) {
                return true;
            }
        }
        return false;
    }
@Dimon94

This comment has been minimized.

Copy link

commented Aug 6, 2018

Hi @elihart, What is the best way to handles the TextWatcher and callback to rebuild models?
Now I use setOnFocusChangeListener() and unbind() to rebuild models.And I don't find the more clean way to handles the TextWatcher.I look forward to an official wiki entry and sample. Thx!

@khatv911

This comment has been minimized.

Copy link

commented Aug 29, 2018

My Approach is:

  • Create a custom Edittext that can manage its Textwatchers list. https://www.dowemo.com/article/57422/how-to-delete-all-listene-added-with-addtextchangedlistener

  • The form item Model should have a textwatcher

  • When bind the text to the edittext :
    +Remove all textwatcher (ideally, at the point, it will be 0 or 1 textwatcher) attached to the edittext.
    +Set the text to the edittext (no textWatcher will be invoked)
    +edittext.addTextWatcher(textwatcher)

  • You may consider to remove the textwacher on OnUnbind event.

  • You may want to add a callback , say OnValueChange(T) in your base FormItem class.

  • aftertextchange will invoke the callback

  • Your ModelController should handle call the callbacks.

  • Use Builder pattern for the object you want to get when hit Summit form

@shakil807g

This comment has been minimized.

Copy link

commented Aug 29, 2018

please add an sample for it .

@alouanemed

This comment has been minimized.

Copy link

commented Oct 18, 2018

Do we have a sample in the Wiki for this as Eli mentioned? Thanks.

@elihart

This comment has been minimized.

Copy link
Contributor

commented Oct 18, 2018

No, this hasn't been done yet. I'll update this issue when it is.

If anyone wants to help that would be great

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.