How to databind to onTextChanged for an EditText on Android?

后端 未结 9 1143
悲哀的现实
悲哀的现实 2020-11-30 01:41

In Yigit Boyar and George Mount\'s talk on Android Databinding they illustrate how easy it is to bind to TextWatcher\'s onTextChanged (at 13:41). O

相关标签:
9条回答
  • 2020-11-30 02:05
    1. create a class (I named him BindingAdapters). Then define your bindingAdapter methods.

      @BindingAdapter("app:textChangedListener")
      fun onTextChanged(et: EditText, number: Int) {
      et.addTextChangedListener(object : TextWatcher {
          override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
              if (et.text.toString().trim().length >= number) {
                  et.setBackgroundColor(Color.GREEN)
              }
          }
      
          override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
          override fun afterTextChanged(s: Editable) {}
      })
      

      }

    2. set this attr for editText in xml layout

      <EditText
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      app:textChangedListener="@{3}" />  
      
    0 讨论(0)
  • 2020-11-30 02:06

    the best way for this is adding bind adapter and a text watcher.

    public class Model{
        private TextWatcher textWatcher;
    
    public Model(){
            this.textWatcher= getTextWatcherIns();
    }
    
    private TextWatcher getTextWatcherIns() {
            return new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                    //do some thing
                }
    
                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                    //do some thing
    
                }
    
                @Override
                public void afterTextChanged(Editable s) {
                    //do some thing
                }
            };
        }
    
        public TextWatcher getTextWatcher() {
            return textWatcher;
        }
    
        public void setTextWatcher(TextWatcher textWatcher) {
            this.textWatcher = textWatcher;
        }
    
        @BindingAdapter("textChangedListener")
        public static void bindTextWatcher(EditText editText, TextWatcher textWatcher) {
            editText.addTextChangedListener(textWatcher);
        }
    }
    

    and in your xml add this attr to your edit text

    <EditText
                android:id="@+id/et"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:textChangedListener="@{model.textWatcher}" />
    
    0 讨论(0)
  • 2020-11-30 02:08

    Actually it works out of the box. I think my mistake was using an old version of the data binding framework. Using the latest, this is the procedure:

    View:

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/username"
        android:text="Enter username:"
        android:onTextChanged="@{data.onTextChanged}" />
    

    Model:

    public void onTextChanged(CharSequence s, int start, int before, int count) {
        Log.w("tag", "onTextChanged " + s);
    }
    

    Make also sure that you have assigned model into DataBinding

    For ex. in your activity

    lateinit var activityMainDataBinding: ActivityMainBinding
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        activityMainDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main) 
        val dataViewModel = ViewModelProvider(this).get(DataViewModel::class.java)
        activityMainDataBinding.dataModel = dataViewModel
    }
    

    Make sure you are referncing gradle build tools v1.5.0 or higher and have enabled databinding with android.dataBinding.enabled true in your build.gradle.

    edit: Functioning demo project here. view. model.

    0 讨论(0)
  • 2020-11-30 02:14

    Attach an setOnFocusChangeListener to the EditText, and use compare the textual content with a global variable (of the previous state/content of the field) to determine whether it has changed:

        mEditTextTitle.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if(!hasFocus)
                    // check if text has changed       
            }
        });
    
    0 讨论(0)
  • 2020-11-30 02:20

    To extend @Nilzors answer, it is also possible to pass text and/or other parameters in the layout:

    View:

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/username"
        android:text="Enter username:"
        android:onTextChanged="@{(text, start, before, count) -> viewModel.onUsernameTextChanged(text)}" />
    

    ViewModel:

    public void onUsernameTextChanged(CharSequence text) {
        // TODO do something with text
    }
    

    You always need to pass either zero or all parameters.

    0 讨论(0)
  • 2020-11-30 02:20

    The Easy Way

    If you are using onTextChange() to have updated text in model then you can directly use Two-way Binding.

    <data>
        <variable
            name="user"
            type="com.package.User"/>
    </data>
    
    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@={user.name}"/>
    

    And you model class will have getter & setter.

    public class User {
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    

    Now the Name in Model will be changed realtime with user interaction. So whenever use binding.getUser().getName(), you will get latest text.

    One-Way Binding will only gets updated when model value is changed. It does not update model back real time.

    android:text="@{user.name}"
    

    Two-Way Binding update model variable in real time with user input.

    android:text="@={user.name}"
    

    The ONLY difference is of = (equal sign) receives data changes to the property and listen to user updates at the same time.

    0 讨论(0)
提交回复
热议问题