Android片段替换仅适用于onCreate

时间:2016-02-29 23:31:12

标签: android android-fragments

我一直在寻找/挣扎这两天了,我真的希望这不是什么傻事。我想替换一个片段。这两个片段正在活动中的同一容器中交换。如果我在OnCreate()中交换代码, BOTH 片段会单独加载,但是当我尝试从回调中替换片段时,我得到了错误。它似乎无法解决容器'R.id.authparent'。但是,在onCreate()中它解析得很好。

以下是deatails: 我有我的活动。这是ViewModel调用onRegisterNewUser()的地方被调用,片段应该被替换。

Activiy Class

public class AuthenticationActivity extends AppCompatActivity implements IAuthenticationActivity {
FragmentManager mgr;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_authentication);
    Fragment loginFragment = new LoginFragment();
    mgr = getSupportFragmentManager();
    FragmentTransaction trans = mgr.beginTransaction();
    trans.add(R.id.authparent, loginFragment, Constants.LOGIN_FRAGMENT);
    trans.commit();
}

@Override
public void onRegisterNewUser() {
    Fragment fragment = new RegisterFragment();
    FragmentTransaction trans = mgr.beginTransaction();
    trans.replace(R.id.authparent, fragment);
    trans.addToBackStack(null);
    trans.commit();
}
}

登录片段

public class LoginFragment extends Fragment {

private static final String TAG = "LoginFragment";
private LoginViewModel viewModel;
@Bind(R.id.input_email)
EditText _emailText;
@Bind(R.id.input_password) EditText _passwordText;
@Bind(R.id.btn_login)
Button _loginButton;
@Bind(R.id.link_signup)
TextView _signupLink;
@Bind(R.id.login_progress)
ProgressBar _progressBar;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_login, container, false);
    ButterKnife.bind(view);

    viewModel = new LoginViewModel(getContext());
    FragmentLoginBinding binding = DataBindingUtil.setContentView(getActivity(), R.layout.fragment_login);
    binding.setViewModel(viewModel);
    return view;
}
}

注册片段

public class RegisterFragment extends Fragment implements IRegisterFragment {
private OAuthToken oauthToken = null;
private static final String TAG = "RegisterFragment";
private RegisterViewModel viewModel;
@Bind(R.id.input_email)
EditText _emailText;
@Bind(R.id.input_username)
EditText _usernameText;
@Bind(R.id.input_password)
EditText _passwordText;
@Bind(R.id.input_verify_password)
EditText _verifyPasswordText;
@Bind(R.id.btn_register)
Button _registerButton;
@Bind(R.id.register_progress)
ProgressBar _progressBar;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_register, container, false);
    ButterKnife.bind(view);
    viewModel = new RegisterViewModel(getContext());
    FragmentRegisterBinding binding = DataBindingUtil.setContentView(getActivity(), R.layout.fragment_register);
    binding.setViewModel(viewModel);
    return view;
}
}

登录ViewModel 这部分是为了节省空间,我唯一要包含的是回调活动的回调

public class LoginViewModel extends ViewModelBase implements ILoginCallBack     {
...

public void onSignupLink(View view) {
    if (context instanceof IAuthenticationActivity) {
        ((IAuthenticationActivity) context).onRegisterNewUser();
    }
}
...
}

ViewModelBase非常简单 的 ViewModelBase

public class ViewModelBase extends BaseObservable {
protected final Context context;

protected Context getContext(){
    return context;
}

public ViewModelBase(Context context) {
    this.context = context;
}

protected boolean checkEmpty(CharSequence s) {
    if (s.toString().isEmpty()) {
        return true;
    }
    return false;
}

}

最后意见: 的 activity_authentication

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/authparent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true">

</RelativeLayout>

fragment_login

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
android:keepScreenOn="true">
<data>
    <variable name="viewModel" type="com.savij.splitr.viewmodels.LoginViewModel" />
</data>
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:fitsSystemWindows="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

    <ProgressBar
        android:id="@+id/login_progress"
        android:visibility="@{viewModel.ProgressBarVisibility}"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        />

<LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingTop="46dp"
    android:paddingLeft="24dp"
    android:paddingRight="24dp"
    android:layout_alignParentTop="true">

    <ImageView android:src="@drawable/splitr_logo_crop"
        android:layout_width="wrap_content"
        android:layout_height="250dp"
        android:layout_gravity="center_horizontal" />
    <!--<TextView-->
        <!--android:layout_width="wrap_content"-->
        <!--android:layout_height="wrap_content"-->
        <!--android:text="@string/app_title"-->
        <!--android:textSize="@dimen/font_title"-->
        <!--android:layout_marginBottom="24dp"-->
        <!--android:layout_gravity="center_horizontal" />-->

    <!-- Email Label -->
    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp"
        app:hintTextAppearance="@style/TextAppearence.App.TextInputLayout">
        <EditText android:id="@+id/input_email"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="textEmailAddress"
            android:text="@{viewModel.Email}"
            android:onTextChanged="@{viewModel.emailChanged}"
            android:error="@{viewModel.EmailError}"
            android:hint="Email"
            android:singleLine="true"/>
    </android.support.design.widget.TextInputLayout>

    <!-- Password Label -->
    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp"
        app:hintTextAppearance="@style/TextAppearence.App.TextInputLayout">
        <EditText android:id="@+id/input_password"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{viewModel.Password}"
            android:onTextChanged="@{viewModel.passwordChanged}"
            android:error="@{viewModel.PasswordError}"
            android:inputType="textPassword"
            android:hint="Password"
            android:singleLine="true"/>
    </android.support.design.widget.TextInputLayout>

    <android.support.v7.widget.AppCompatButton
        android:id="@+id/btn_login"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:layout_marginBottom="24dp"
        android:padding="12dp"
        android:text="Login"
        android:onClick="@{viewModel.onClickLogin}"
        />

    <TextView android:id="@+id/link_signup"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="24dp"
        android:text="No account yet? Create one"
        android:onClick="@{viewModel.onSignupLink}"
        android:gravity="center"
        android:textSize="16dip"/>

    <TextView android:id="@+id/link_lost_password"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="24dp"
        android:text="Forgot password?"
        android:onClick="@{viewModel.onForgotPassword}"
        android:gravity="center"
        android:textSize="16dip"/>

</LinearLayout>

fragment_register

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
android:keepScreenOn="true">
<data>
    <variable name="viewModel" type="com.savij.splitr.viewmodels.RegisterViewModel" />
</data>
<ScrollView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:fitsSystemWindows="true">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ProgressBar
            android:id="@+id/register_progress"
            android:visibility="@{viewModel.ProgressBarVisibility}"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            />

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingTop="46dp"
            android:paddingLeft="24dp"
            android:paddingRight="24dp"
            android:layout_alignParentTop="true">

            <ImageView android:src="@drawable/splitr_logo_solo"
                android:layout_width="wrap_content"
                android:layout_height="100dp"
                android:layout_gravity="center_horizontal" />

            <!-- Email Label -->
            <android.support.design.widget.TextInputLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:layout_marginBottom="8dp"
                app:hintTextAppearance="@style/TextAppearence.App.TextInputLayout">
                <EditText android:id="@+id/input_email"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:inputType="textEmailAddress"
                    android:text="@{viewModel.Email}"
                    android:onTextChanged="@{viewModel.emailChanged}"
                    android:error="@{viewModel.EmailError}"
                    android:hint="Email"
                    android:singleLine="true"/>
            </android.support.design.widget.TextInputLayout>

            <android.support.design.widget.TextInputLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:layout_marginBottom="8dp"
                app:hintTextAppearance="@style/TextAppearence.App.TextInputLayout">
                <EditText android:id="@+id/input_username"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:inputType="textEmailAddress"
                    android:text="@{viewModel.Username}"
                    android:onTextChanged="@{viewModel.usernameChanged}"
                    android:error="@{viewModel.UsernameError}"
                    android:hint="Username"
                    android:singleLine="true"/>
            </android.support.design.widget.TextInputLayout>

            <!-- Password Label -->
            <android.support.design.widget.TextInputLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:layout_marginBottom="8dp"
                app:hintTextAppearance="@style/TextAppearence.App.TextInputLayout">
                <EditText android:id="@+id/input_password"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="@{viewModel.Password}"
                    android:onTextChanged="@{viewModel.passwordChanged}"
                    android:error="@{viewModel.PasswordError}"
                    android:inputType="textPassword"
                    android:hint="Password"
                    android:singleLine="true"/>
            </android.support.design.widget.TextInputLayout>

            <android.support.design.widget.TextInputLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:layout_marginBottom="8dp"
                app:hintTextAppearance="@style/TextAppearence.App.TextInputLayout">
                <EditText android:id="@+id/input_verify_password"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="@{viewModel.VerifyPassword}"
                    android:onTextChanged="@{viewModel.verifyPasswordChanged}"
                    android:error="@{viewModel.VerifyPasswordError}"
                    android:inputType="textPassword"
                    android:hint="Verify Password"
                    android:singleLine="true"/>
            </android.support.design.widget.TextInputLayout>

            <android.support.v7.widget.AppCompatButton
                android:id="@+id/btn_register"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="24dp"
                android:layout_marginBottom="24dp"
                android:padding="12dp"
                android:text="Login"
                android:onClick="@{viewModel.onClickRegister}"
                />

            <TextView android:id="@+id/link_signup"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="24dp"
                android:text="Already have an account?"
                android:onClick="@{viewModel.onLoginLink}"
                android:gravity="center"
                android:textSize="16dip"/>

        </LinearLayout>

    </RelativeLayout>

</ScrollView>
</layout>

我得到的错误是:

02-29 17:23:24.340 8064-8064/com.savij.splitr E/FragmentManager: Activity state:
02-29 17:23:24.370 8064-8064/com.savij.splitr E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.savij.splitr, PID: 8064
java.lang.IllegalArgumentException: No view found for id 0x7f0c006c (com.savij.splitr:id/authparent) for fragment RegisterFragment{a34c76c #1 id=0x7f0c006c}
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1059)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1252)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:517)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5835)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)

很奇怪,它第一次解决了,但在回调中它会爆炸。任何帮助将不胜感激! 谢谢, 杰夫

1 个答案:

答案 0 :(得分:0)

所以我找到了答案,这很有道理。我认为这对我来说真的是新材料所以我没想到要看实用程序上的其他DataBinding方法。

在我的LoginFragment类中,我有不正确的代码行:

FragmentLoginBinding binding = DataBindingUtil.setContentView(getActivity(),
R.layout.fragment_login);

实际上,我不想设置内容视图。上面几行,我正在膨胀我需要的观点,所以我应该一直在努力。修正后的行只是:

FragmentLoginBinding binding = DataBindingUtil.bind(view);

为什么在尝试更换下一个片段时它会爆炸真的是一个奇怪的副产品,但我很高兴我找到了答案!希望它也可以帮助其他人!