14

I am currently using databinding for my android application project. I want to set the error message on my CustomTextView from R.string.txtOldPassWordError and set it up from another class called ViewModelClass.

Here is my XML code

<com.horseproject.widget.CustomEditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center_vertical"
    android:layout_marginTop="@dimen/dp_20"
    android:drawablePadding="@dimen/dp_10"
    android:hint="@string/enter_old_password"
    android:inputType="textPassword"
    android:lines="1"
    android:text="@={ChangePasswordVM.userOldPassword}"
    android:textColorHint="@color/gray_text"
    app:drawableLeftCompat="@drawable/ic_password_lock"
    app:drawableTintCompat="@color/gray_app"
    app:error="@{ChangePasswordVM.userOldPasswordError}" />

and this is ViewModelClass.java

public class ChangePasswordViewModel extends BaseObservable {

    public ObservableField<String> userOldPassword = new ObservableField<>("");

    public void userPasswordChange() {

        if ((TextUtils.isEmpty(userOldPassword.get()))) {
            userOldPasswordError.set("Please enter your old password");
            return;
        } else if (userOldPassword.get().length() <= 5) {
            userOldPasswordError.set("Password should contain minimum 6 characters");
            return;
        } else {
            userOldPasswordError.set(null);
        }
    }
}

and this is string from strings.xml

<string name="select">Please Enter Old Password</string>

So, I want to access this string in my viewModel class and set it as error message instead of hardcoded it directly as string.

So how can i achieve this? I am using Android Studio 3.0 Beta Version. Any help would be really appreciated.

Ravi Vaniya
  • 1,562
  • 1
  • 17
  • 28
  • getResources().getString(R.string.select); or refer this https://stackoverflow.com/questions/7493287/android-how-do-i-get-string-from-resources-using-its-name – Sagar Aghara Oct 10 '17 at 12:22
  • i have tried this @SagarAghara, but is says "can not resolve method 'getResources' ", thx for efforts –  Oct 10 '17 at 12:26
  • that is because getResources needs context. Are you using MVVM architecture by any chance. Could you not pass the string from a activity or fragment via constructor? – Raghunandan Oct 10 '17 at 12:35

3 Answers3

13

Using an ObservableInt worked for me. Adding this to the ViewModel

private final ObservableInt mErrorText = new ObservableInt(R.string.empty_text);

public ObservableInt getErrorText() {
   return mErrorText;
}

And just setting a new String value

mErrorText.set(R.string.text_not_valid);

In the xml add the following to the TextView

android:text="@{viewModel.errorText}"
latsson
  • 630
  • 7
  • 8
  • I agree this should be the correct answer. As the accepted answer relies on the context in the view model. Is there any way the string could be cleared or set to "" using this method? – Alex Gray Nov 12 '18 at 15:40
  • i get android.content.res.Resources$NotFoundException: String resource ID #0x0 by applying the same – Srishti Roy Jan 07 '19 at 08:58
  • @SrishtiRoy do you have the R.string.empty_text in your strings.xml? Change to what your own string or add this – latsson Jan 07 '19 at 10:13
  • 1
    @AlexGray If you have the empty_text you should be able to set it to clear the textfield. You could also create a BindingAdapter that checks if the text is null or empty and in that case set the textView visibility to GONE – latsson Jan 07 '19 at 10:16
  • `ObservableInt` type does not seem to work with `"tools:error"` on `TextInputLayout`. The only thing that works is `BindableString`. How do I bind `ObservableInt` with `BindableString`? – Sergiy Belozorov Jan 15 '19 at 10:51
10

Create ResourceProvider class

public class ResourceProvider {

    private Context mContext;

    public ResourceProvider(Context mContext) {
        this.mContext = mContext;
    }

    public String getString(int resId) {
        return mContext.getString(resId);
    }

    public String getString(int resId, String value) {
        return mContext.getString(resId, value);
    }
}

now go to your ApplicationClass and paste

public class YourAppName extends Application {
  // Resource Provider
    private ResourceProvider mResourceProvider;
    public ResourceProvider getResourceProvider() {
        if (mResourceProvider == null)
            mResourceProvider = new ResourceProvider(this);

        return mResourceProvider;
    }
}

now go to your ChangePasswordViewModel and create object of ResourceProvider

private ResourceProvider mResourceProvider;

and pass it in constroctor of ChangePasswordViewModel

than you can access it by

 userOldPasswordError.set(mResourceProvider.getString(R.string.select));
Ravi Vaniya
  • 1,562
  • 1
  • 17
  • 28
3

You can send context into the layout like this :

XML :

<!-- 
<data>
     <variable 
          name="observable"
          type="...MyBaseObservableClass"
     />
</data>
 -->

android:text="@{observable.getDescription(context)}"

MyBaseObservableClass.kt :

@Bindable
fun getDescription(context: Context): String {
    return context.getString(R.string.my_string)
}

fun setNewData(data: Object) {
     this.data = data
     notifyPropertyChanged(BR.description)
}
Johnny
  • 2,989
  • 4
  • 17
  • 28