3

Is there some way to provide android:maxLength attribute via two-way databinding in Android application?

What i currently have is this in XML:

<EditText
                        android:id="@+id/edBody"
                        style="@style/SimpleEdit"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:clickable="false"
                        android:hint="@string/ComposeMessage"
                        android:text="@={viewModel.composeFace.body}"
                        android:maxLength="@={viewModel.inReplyMode ? viewModel.maxReplyLength : viewModel.maxMessageLength}"
                        android:afterTextChanged="@{viewModel.autoWatch}"
                        android:imeOptions="actionNext"
                        android:inputType="textMultiLine"/>

In view model i have these attributes:

/**
 * Maximum length of message body.
 */
@Bindable
public int maxMessageLength;

/**
 * Maximum length of reply message body.
 */
@Bindable
public int maxReplyLength;

Error thrown during build:

> java.lang.RuntimeException: Found data binding errors.
****/ data binding error ****msg:Cannot find the getter for attribute 'android:maxLength' with value type int on android.widget.EditText.
file:...\app\src\main\res\layout\f_message_compose.xml
loc:66:20 - 77:65
****\ data binding error ****

I understand that this error is thrown because there is no simple set method for text length and it is usually provided via InputFilter as described here: How to programmatically set maxLength in Android TextView?

What i can imagine it to work would be something like:

android:maxLength="@={viewModel.replyLength}"

with

@Bindable
public InputFilter[] getReplyLength() {
    return isInReplyMode() ? new InputFilter[] { new InputFilter.LengthFilter(maxReplyLength) } : new InputFilter[] { new InputFilter.LengthFilter(maxMessageLength) };
}

but it will not work for obvious reasons. It actually results into:

> java.lang.RuntimeException: Found data binding errors.
****/ data binding error ****msg:The expression ((viewModelInReplyMode) ? (viewModelMaxReplyLength) : (viewModelMaxMessageLength)) cannot cannot be inverted: The condition of a ternary operator must be constant: android.databinding.tool.writer.KCode@7f305219
file:...\app\src\main\res\layout\f_message_compose.xml
loc:74:50 - 74:126
****\ data binding error ****

So is there any possible way to data-bind max length attribute?

Community
  • 1
  • 1
Pepa Novotný
  • 126
  • 1
  • 13
  • 1
    there is a `BindingAdapter` for `android:maxLength`, see: http://androidxref.com/7.1.1_r6/xref/frameworks/data-binding/extensions/baseAdapters/src/main/java/android/databinding/adapters/TextViewBindingAdapter.java#238, what do you need two-way binding for? – pskink Mar 08 '17 at 08:46
  • Well, if i understand it correctly, this adapter should be used by default. Anyway your question led me to the problem. It seems like I should not have put `@=` in front of attribute, but use only `@`! That's the difference between databinding and two way databinding. Seems like i missed it in specification :) – Pepa Novotný Mar 08 '17 at 09:15
  • 1
    `@=` is used when for ex. `EditText` wants to bind some model string and display it as the content and back when you change it the changes should be mapped to the string model – pskink Mar 08 '17 at 09:25
  • Yeah, i understand the difference now and it was clearly caused by my inattention to the syntax of databinding and therefore usage of 2-way-databinding instead of simple databinding for inappropriate attribute. Thank you for pointing it out :) – Pepa Novotný Mar 08 '17 at 09:28
  • 1
    Instead of an edit, answer your question yourself if it was solved by you with one of the comments. – tynn Mar 08 '17 at 11:25
  • ok, thanks for hint - i can accept it tomorrow after 48h had passed – Pepa Novotný Mar 08 '17 at 11:48

1 Answers1

0

As was pointed by @pskink in comments - my problem was the usage of two way databinding instead of databinding for maxLength attribute. There should be:

android:maxLength="@{viewModel.inReplyMode ? viewModel.maxReplyLength : viewModel.maxMessageLength}"

instead of

android:maxLength="@={viewModel.inReplyMode ? viewModel.maxReplyLength : viewModel.maxMessageLength}"

That's why there was "no getter method for android:maxLength attribute of TextView" exception.

Pepa Novotný
  • 126
  • 1
  • 13