8

我正在学习结构并使用结构mvvm制作应用程序。mvvmdata binding

现在,我想做的是,我想从 sharedpreference 中获取一个用户,如果我成功获取了一个用户,我会将 usr 的名称设置为edittext1. 在这种情况下,我想请求关注 edittext2

如何使用数据绑定来实现?(以这样的方式,我不必使用活动。这项工作应该只使用视图模型和 xml 来完成。)

我已经尝试过使用以下方式。

开始游戏视图模型

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>

开始游戏活动:

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);
        });
    }
}
4

2 回答 2

7

通过绑定适配器非常简单

@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}" />
于 2018-11-01T11:19:09.357 回答
3

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

在 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布尔值作为属性的值给出app:requestFocus

就我而言,我不想移除焦点,这就是我使用布尔值的原因。如果需要更改,使用 alivedata并设置值,并相应地更新绑定适配器

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

于 2019-09-15T16:44:42.923 回答