java - Android MVVM 与数据绑定(bind)

标签 java android mvvm

我正在玩 android,这没有真正的目的,只是为了发现东西。

所以我有一个textWatcher和2个editText框,当用户更改文本时如何更改文本的颜色?

例如,假设如果用户输入字母以外的内容,则文本必须为红色。

对于性能问题(这相关吗?)我希望表单中需要相同验证规则的所有字段只有一个 textWatcher(我在互联网上找到的每个教程每个字段都有 1 个观察者,也许这是有原因的)

一开始我想使用 android:addTextChangedListener= 但这不会将 edittext 对象发送给观察者,所以我知道“一个字段”已更改,但不知道是哪个字段。

我有这个:

View (3 个字段、2 个文本和 1 个数字)

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="basicForm"
            type="com.example.mvvm.databinding.BasicForm" />
    </data>

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/constraint"
    tools:context="com.example.mvvm.databinding.MainActivity">

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        tools:layout_editor_absoluteX="0dp"
        tools:layout_editor_absoluteY="0dp">

        <EditText
            android:id="@+id/nameField"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="241dp"
            android:ems="10"
            android:hint="@{basicForm.fieldName}"
            android:inputType="textPersonName"
            android:layout_alignParentTop="true"
            android:layout_alignStart="@+id/lastnameField" />

        <EditText
            android:id="@+id/lastnameField"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ems="10"
            android:textColor="#00FF00"
            android:hint="@{basicForm.fieldLastName}"
            android:inputType="textPersonName"
            android:layout_marginBottom="81dp"
            android:layout_alignBottom="@+id/nameField"
            android:layout_centerHorizontal="true" />


        <EditText
            android:id="@+id/phoneField"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignStart="@+id/nameField"
            android:layout_below="@+id/nameField"
            android:layout_marginTop="35dp"
            android:ems="10"
            android:hint="@{basicForm.fieldPhone}"
            android:inputType="textPersonName" />

    </RelativeLayout>

</android.support.constraint.ConstraintLayout>
</layout>

主要 Activity :

package com.example.mvvm.databinding;

import android.databinding.DataBindingUtil;
import android.os.Bundle;

import com.example.mvvm.databinding.databinding.ActivityMainBinding;

public class MainActivity extends FormActivity {

    ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        final BasicForm bf = new BasicForm();
        bf.setFieldPhone("06XXXXXXXX");
        bf.setFieldName("Name");
        bf.setFieldLastName("Last Name");
        bf.setStringWatcher(getStringWatcherInstance());
        bf.setPhoneWatcher(getPhoneWatcherInstance());
        binding.setBasicForm(bf);
    }

}

主要 Activity 的父级:

package com.example.mvvm.databinding;

import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.TextWatcher;

import java.util.regex.Pattern;

public class FormActivity extends AppCompatActivity {

    private static TextWatcher stringWatcherInstance = null;
    private static TextWatcher phoneWatcherInstance = null;

    public boolean stringContainsOnlyChar(String s) {
        if(! Pattern.matches(".*[a-zA-Z]+.*[a-zA-Z]", s)) {
            return true;
        }
        return false;
    }

    public synchronized TextWatcher getStringWatcherInstance() {
        if(stringWatcherInstance == null) {
            stringWatcherInstance = new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {

                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                    if (stringContainsOnlyChar(s.toString())) {
                        //set color of calling edit box to black
                    }
                    //set color of calling edif box to red

                }

                @Override
                public void afterTextChanged(Editable s) {

                }
            };

        }
        return stringWatcherInstance;
    }

    public synchronized TextWatcher getPhoneWatcherInstance() {
        if(phoneWatcherInstance == null) {
            phoneWatcherInstance = new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {

                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {

                }

                @Override
                public void afterTextChanged(Editable s) {

                }
            };

        }
        return phoneWatcherInstance;
    }

}

和用于数据绑定(bind)的 BasicForm 对象:

package com.example.mvvm.databinding;
import android.databinding.BaseObservable;
import android.databinding.Bindable;
import android.text.TextWatcher;

public class BasicForm extends BaseObservable {

    private String fieldName;
    private String fieldLastName;
    private String fieldPhone;

    public BasicForm() {}

    @Bindable
    public String getFieldName() {

        return fieldName;
    }

    public void setFieldName(String FieldName) {
        this.fieldName = FieldName;
        notifyPropertyChanged(BR.fieldName);
    }

    @Bindable
    public String getFieldLastName() {
        return fieldLastName;
    }

    public void setFieldLastName(String fieldLastName) {
        this.fieldLastName = fieldLastName;
    }

    @Bindable
    public String getFieldPhone() {
        return fieldPhone;
    }

    public void setFieldPhone(String fieldPhone) {
        this.fieldPhone = fieldPhone;
        notifyPropertyChanged(BR.fieldPhone);
    }

}

所以基本上我想要的只是一个可以在 xml 中关联的“charOnlyTextWatcher”,然后在它的 onChange() 方法中可以作用于调用者(触发 onChange() 的 edittext 对象)

我是不是在做一些毫无用处的事情?错了?

谢谢。

最佳答案

For example let's say that if the user put something else than a letter then the text has to be red.

首先让我们构建 ViewModel:

@Bindable public Color getTextColor(){
      return mSomeText.length() == 1? Color.Black : Color.Red; 
}

public void onInputChanged(Editable editable){
     mSomeText = editable.toString();
     notifyPropertyChanged(BR.textColor); 
}

现在您正在监听输入更改并导致属性更改,让我们编写layout.xml:

    <EditText
        ...
        android:afterTextChanged="{@viewModel::onInputChanged}" 
        android:textColor="@{viewModel.textColor}" />

您已准备好开始,无需更多代码。
希望对您有所帮助。

关于java - Android MVVM 与数据绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45616606/

相关文章:

java - Android - 使用 GridLayout 垂直滚动

java - 获取 SQLite 单列结果列表的快速方法

android - view 在 MVVM 中向 ViewModel 请求数据是否可以?

Android 添加某些权限后无法调试

android - 如何根据各种设备获取短信列表

c# - ViewModel 的版本控制

c# - 从嵌套用户控件(MVVM)导出数据

java - openam客户端sdk session ID无效

java - 如何无限地生成随机数,直到它符合Java中的条件?

java - JUnit 与 Rails Fixtures 并行吗?