如何使用数据绑定请求或删除对edittext的关注

时间:2018-04-16 09:10:00

标签: android mvvm android-databinding android-mvvm

我正在学习mvvm结构,并使用mvvm结构和data binding制作应用。

现在,我想要做的是,我想从共享偏好中获取用户,如果我成功获得用户,我会将usr的名称设置为edittext1。在这种情况下,我想请求专注于edittext2

  

如何使用数据绑定实现这一目标? (以这种方式,我不会   必须使用活动。应该使用视图模型和xml完成​​这项工作   仅。)

我尝试过使用以下方式。

StartGameViewModel

public class StartGameViewModel extends ViewModel {

    public static String TAG="StartGameViewModel";

    private Preference<User> preference;
    public ObservableField<String> player1Name=new ObservableField<>("");
    public ObservableField<String> player2Name=new ObservableField<>("");

    public ObservableBoolean shouldRequestFocus=new ObservableBoolean(false);


    StartGameViewModel(Preference preference){
        this.preference=preference;
    }

    public void getPreference() {
        preference.get(Constants.CURRENT_USER,User.class)
                .subscribe(new Observer<User>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(User user) {
                        player1Name.set(user.name);
                        shouldRequestFocus.set(true);
                    }

                    @Override
                    public void onError(Throwable e) {
                       Log.i(TAG,"user is logged out");
                    }

                    @Override
                    public void onComplete() {
                        Log.i(TAG,"Completed Preference");
                    }
                });
    }
}

activity_start_game.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".view.StartGameActivity">

    <data>
        <variable
            name="startGameViewModel"
            type="com.sevenbits.android.mvvmsample.viewmodel.StartGameViewModel" />
    </data>

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/splash_bg">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Enter Players Name"
            android:textSize="24sp"
            android:textColor="@color/white"
            app:layout_constraintVertical_bias="0.75"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintBottom_toTopOf="@+id/input_layout"
            app:layout_constraintTop_toTopOf="parent"
            />

        <LinearLayout
            android:id="@+id/input_layout"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="40dp"
            android:layout_marginRight="40dp"
            android:background="@color/white"
            android:elevation="20dp"
            android:orientation="vertical"
            android:paddingBottom="40dp"
            android:paddingLeft="20dp"
            android:paddingRight="20dp"
            android:paddingTop="40dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.45"
            tools:layout_editor_absoluteX="8dp">

            <android.support.design.widget.TextInputLayout
                android:id="@+id/til_name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="10dp">

                <android.support.design.widget.TextInputEditText
                    android:id="@+id/et_player1"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="Player1"
                    android:text="@{startGameViewModel.player1Name}"
                    app:addTextChangedListener="@{startGameViewModel.Player1Watcher}" />

            </android.support.design.widget.TextInputLayout>


            <android.support.design.widget.TextInputLayout
                android:id="@+id/til_password"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="10dp">

                <android.support.design.widget.TextInputEditText
                    android:id="@+id/et_player2"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="Player2"
                    android:text="@{startGameViewModel.player2Name}"
                    app:addTextChangedListener="@{startGameViewModel.Player2Watcher}" />

            </android.support.design.widget.TextInputLayout>

        </LinearLayout>

        <Button
            android:id="@+id/start_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/bg_button"
            android:elevation="20dp"
            android:gravity="center"
            android:paddingBottom="20dp"
            android:paddingEnd="40dp"
            android:paddingStart="40dp"
            android:paddingTop="20dp"
            android:text="Start"
            android:textAllCaps="false"
            android:textColor="@color/white"
            android:textSize="18sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/input_layout" />

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

StartGameActivity:

public class StartGameActivity extends AppCompatActivity {

    ActivityStartGameBinding activityStartGameBinding;
    StartGameViewModel startGameViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initDataBinding();
        setStartGameListener();
    }

    private void initDataBinding() {
        activityStartGameBinding = DataBindingUtil.setContentView(this, R.layout.activity_start_game);

        StartGameViewModelFactory startGameViewModelFactory= Injection.provideStartGameViewModelFactory(this);
        startGameViewModel = ViewModelProviders.of(this,startGameViewModelFactory).get(StartGameViewModel.class);
        activityStartGameBinding.setStartGameViewModel(startGameViewModel);

        startGameViewModel.getPreference();
        if(startGameViewModel.shouldRequestFocus.get())
            findViewById(R.id.et_player2).requestFocus();
    }

    private void setStartGameListener() {
        findViewById(R.id.start_button).setOnClickListener(v -> {
            Intent intent=new Intent(StartGameActivity.this,GameActivity.class);
            intent.putExtra(Constants.PLAYER1_NAME,startGameViewModel.player1Name.get());
            intent.putExtra(Constants.PLAYER2_NAME,startGameViewModel.player2Name.get());
            startActivity(intent);
        });
    }
}

2 个答案:

答案 0 :(得分:2)

通过绑定适配器非常简单

@JvmStatic
@BindingAdapter("requestFocus")
fun requestFocus(view: TextView, requestFocus: Boolean) {
    if (requestFocus) {
        view.isFocusableInTouchMode = true
        view.requestFocus()
    }
}



             <EditText
                android:id="@+id/et_company"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:imeOptions="actionDone"
                android:inputType="textCapSentences"
                android:maxLength="32"
                android:scrollbars="vertical"

                app:requestFocus="@{company.requestFocus}" />

答案 1 :(得分:0)

我知道这是一个老问题,但是我无法使用当前答案解决该问题。在这里发布我的答案:

在XML中:

<EditText
    android:id="@+id/email"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:elevation="@dimen/elevation15"
    app:requestFocus="@{viewmodel.focus}"/>

在viewModel中,我有一个布尔变量声明为

val focus = true

绑定适配器如下:

companion object{
    @BindingAdapter("requestFocus")
    @JvmStatic fun requestFocus(editText: EditText, requestFocus: Boolean){
        if(requestFocus){
            editText.isFocusableInTouchMode = true
            editText.requestFocus()
        }
    }
}

基本上,这里发生的是,由于app:requestFocus是写在xml内的,它将使用focus布尔值来调用绑定适配器,该布尔值作为{{ 1}}。

就我而言,我不想移除焦点,这就是为什么我使用布尔值。如果需要更改,使用实时数据将起作用并设置值。并相应地更新绑定适配器

免责声明:我是MVVM和数据绑定的新手,如果我错了,请纠正我。