【问题标题】:View visibility is not getting restored from backstack视图可见性未从 backstack 恢复
【发布时间】:2015-08-23 11:26:38
【问题描述】:

我的 Fragment1 xml 布局有:

  • 两个单选按钮,默认未选中
  • 两个 EditText(一个带有 inputType="decimal",另一个带有 inputType="number"),具有 visibility="gone"
  • 一个按钮,同样具有visibility="gone"

所以,最初它们看起来像这样:

然后在单击任一单选按钮时,所需的 EditText 和按钮变为可见,我可以输入值。

单击按钮时,Fragment1 将替换为 Fragment2。 然后在按下后退键时,后退堆栈不会恢复 EditText 和 Button 的可见性信息。它显示了选定的单选按钮,只有在单击它之后,我才能看到带有先前输入值的 EditText 和按钮。

我希望它与按钮一起显示输入的值,而无需单击单选选项。

我的片段 java:

public class Fragment1 extends Fragment {

// Member variables to store the visibility info of the two EditTexts and the button
int visibilityEditTextArea;
int visibilityEditTextNum;
int visibilityBtnEnterStateRec;

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    ... 

    // OnClickListener for the first radio button, "Area of Farm".
    // Sets the visibility of the EditText with inputType="decimal" and the button to be VISIBLE, 
    // and intializes the member variables with the new visibility info.
    RadioButton radioButtonArea = (RadioButton) view.findViewById(R.id.radio_area_of_farm_to_fertilize);
    radioButtonArea.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            Activity activity = getActivity();

            EditText editTextArea = (EditText) activity.findViewById(R.id.editText_area);
            if (editTextArea.getVisibility() == View.GONE) {
                editTextArea.setVisibility(View.VISIBLE);
                visibilityEditTextArea = editTextArea.getVisibility();
            }

            EditText editTextNum = (EditText) activity.findViewById(R.id.editText_number);
            if (editTextNum.getVisibility() == View.VISIBLE) {
                editTextNum.setVisibility(View.GONE);
                visibilityEditTextNum = editTextArea.getVisibility();
            }

            Button btnEnterStateRec = (Button) activity.findViewById(R.id.btn_enter_state_rec);
            if (btnEnterStateRec.getVisibility() == View.GONE) {
                btnEnterStateRec.setVisibility(View.VISIBLE);
                visibilityBtnEnterStateRec = btnEnterStateRec.getVisibility();
            }
        }
    });

    // Similarly for the second radio button.
    RadioButton radioButtonNum = (RadioButton) view.findViewById(R.id.radio_number_of_plants);
    radioButtonNum.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            Activity activity = getActivity();

            EditText editTextArea = (EditText) activity.findViewById(R.id.editText_area);
            if (editTextArea.getVisibility() == View.VISIBLE) {
                editTextArea.setVisibility(View.GONE);
                visibilityEditTextArea = editTextArea.getVisibility();
            }

            EditText editTextNum = (EditText) activity.findViewById(R.id.editText_number);
            if (editTextNum.getVisibility() == View.GONE) {
                editTextNum.setVisibility(View.VISIBLE);
                visibilityEditTextNum = editTextArea.getVisibility();
            }

            Button btnEnterStateRec = (Button) activity.findViewById(R.id.btn_enter_state_rec);
            if (btnEnterStateRec.getVisibility() == View.GONE) {
                btnEnterStateRec.setVisibility(View.VISIBLE);
                visibilityBtnEnterStateRec = btnEnterStateRec.getVisibility();
            }
        }
    });

    // OnClickListener for the Button, "ENTER STATE RECOMMENDATIONS".
    // Puts the member variables in a bundle, and then replaces the container with Fragment2
    Button buttonEnterStateRec = (Button) view.findViewById(R.id.btn_enter_state_rec);
    buttonEnterStateRec.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            // Puts the member variables in a bundle before making fragment transaction
            Bundle outState = new Bundle();
            outState.putInt("visibility_eT_area", visibilityEditTextArea);
            outState.putInt("visibility_eT_num", visibilityEditTextNum);
            outState.putInt("visibility_btn_enterStateRec", visibilityBtnEnterStateRec);
            Fragment1 fragment1 = new Fragment1();
            fragment1.setArguments(outState);

            Fragment2 fragment2 = new Fragment2();
            FragmentTransaction transaction = getFragmentManager().beginTransaction();
            transaction.replace(R.id.fragment_container, fragment2);
            transaction.addToBackStack(null);
            transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
            transaction.commit();
        }
    });


    // Restores the member variables with the arguments from the bundle
    Bundle args = this.getArguments();
    if (args != null) {
        visibilityEditTextArea = args.getInt("visibility_eT_area");
        visibilityEditTextNum = args.getInt("visibility_eT_num");
        visibilityBtnEnterStateRec = args.getInt("visibility_btn_enterStateRec");

        // Checks if the int value of the member variable equals to that of View.VISIBLE.
        // If it does then sets the respective View to be visible.
        if (visibilityEditTextArea == View.VISIBLE) {
            view.findViewById(R.id.editText_area).setVisibility(View.VISIBLE);
        }
        if (visibilityEditTextNum == View.VISIBLE) {
            view.findViewById(R.id.editText_number).setVisibility(View.VISIBLE);
        }
        if (visibilityBtnEnterStateRec == View.VISIBLE) {
            view.findViewById(R.id.btn_enter_state_rec).setVisibility(View.VISIBLE);
        }
    }

    return view;
}

// Overides onPause() to save the visibility arguments in a bundle.
@Override
public void onPause() {
    super.onPause();

    Bundle outState = new Bundle();
    outState.putInt("visibility_eT_area", visibilityEditTextArea);
    outState.putInt("visibility_eT_num", visibilityEditTextNum);
    outState.putInt("visibility_btn_enterStateRec", visibilityBtnEnterStateRec);
    Fragment1 fragment1 = new Fragment1();
    fragment1.setArguments(outState);
}

}

XML 是这样的。我已经删除了 ID 和布局对齐细节。:

<RelativeLayout
    android:focusable="true"
    android:focusableInTouchMode="true">

    ...
    <RadioGroup>

        <RadioButton
            android:text="Area of farm to fertilize" />

        <RadioButton
            android:text="Number of plants or trees" />

    </RadioGroup>

    <android.support.design.widget.TextInputLayout>

        <EditText
            android:hint="In hectare"
            android:inputType="numberDecimal"
            android:visibility="gone"
            tools:visibility="visible" />

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

    <android.support.design.widget.TextInputLayout>

        <EditText
            android:inputType="number"
            android:visibility="gone"
            tools:visibility="visible" />

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

    <Button
        android:text="Enter state recommendations"
        android:visibility="gone"
        tools:visibility="visible" />

</RelativeLayout>

【问题讨论】:

    标签: android android-fragments


    【解决方案1】:

    实际上,FragmentActivity(或 AppCompatActivity)的当前实现将为您完成恢复视图状态的繁琐工作,您所要做的就是给您的 Fragment 一个 id 或标签。

    因此,当添加您的 第一个 片段(或您希望自动保留视图状态的任何片段)时,请执行以下操作:

    // probably in onCreate() of your activity:
    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    // Note the 3rd parameter -- it's the tag
    transaction.add(R.id.fragment_container, fragment1, "FRAGMENT1");
    

    现在,当您将 frag2-frag1 事务从后台堆栈中弹出时,它将被恢复。

    onActivityCreated() 你可以这样:

    public View onActivityCreated(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
        ...
        if (savedInstanceState != null) {
            // pick up stuff from savedInstanceState
            // this is for the cases when onSaveInstanceState() has been called
            // i.e. for when activity's onSaveInstanceState() has been called
            // not for back stack events
        }
    

    并将您的onPause()/onCreateView() 捆绑操作移动到onSaveInstanceState()onActivityCreated()——所有其他情况将由FragmentManager 自动处理。

    【讨论】:

    • 感谢您提及标签参数。我的 add() 中缺少它。 (有关片段中标签重要性的更多信息:stackoverflow.com/a/13510619/1944049)虽然它仍然没有恢复可见性状态。我想我得改变我的设计了。
    【解决方案2】:

    通过在单选按钮上实现 setOnCheckedChangeListener 来修复它。 OnClickListener 没有提供 Compound Buttons 所需的行为,例如复选框、单选按钮、开关和切换按钮。

    【讨论】:

      猜你喜欢
      • 2016-06-24
      • 2014-11-01
      • 2016-05-12
      • 1970-01-01
      • 2023-03-16
      • 2013-08-20
      • 1970-01-01
      • 1970-01-01
      • 2013-04-17
      相关资源
      最近更新 更多