保存CheckBox状态

时间:2016-02-21 02:35:07

标签: android android-fragments testing android-checkbox android-uiautomator

我试图在片段中保存复选框的状态。我有一个测试,以确保在方向更改时恢复复选框状态。测试失败,因为未恢复复选框状态。但是,当我在测试期间单步执行代码时,它似乎按照我期望的方式工作。 enabledFieldsonPause()onSaveInstanceState()onCreate()中具有正确的值。设置filterOptions的正确元素进行检查。但是,它并未在屏幕上显示为已选中状态。我在这里缺少什么?

一些线索:

我有两个单独的测试,如下所示:testSaveInstanceStateBrand()testSaveInstanceStateTeam()。在testSaveInstanceStateBrand()中,方向更改后不会选中复选框。另一方面,在testSaveInstanceStateTeam()中,选中所有复选框。由于我只在一个复选框上调用setChecked(),因此似乎为所有CheckBox绘制了相同的FilterOptionView实例,但在Java代码中,每个FilterOptionView都有引用自己的CheckBox

代码:

FilterCardsTest

@RunWith(AndroidJUnit4.class)
public class FilterCardsTest {
    @Rule
    public ActivityTestRule<FragmentTestActivity> activityTestRule =
            new ActivityTestRule<>(FragmentTestActivity.class);

    private static final int[] IDS =
            {R.id.brand, R.id.year, R.id.number, R.id.player_name, R.id.team};

    private FragmentTestActivity activity = null;
    private UiDevice device;

    @Before
    public void setUp() throws Exception {
        activity = activityTestRule.getActivity();
        activity.replaceFragment(new FilterCards());
        device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
    }

    @After
    public void tearDown() throws RemoteException {
        device.setOrientationNatural();
    }

    @Test
    public void testSaveInstanceStateBrand() throws RemoteException {
        this.testSaveInstanceState(R.id.brand);
    }

    @Test
    public void testSaveInstanceStateTeam() throws RemoteException {
        this.testSaveInstanceState(R.id.team);
    }

    private void testSaveInstanceState(int filterId) throws RemoteException {
        this.testCheckBox(filterId);
        device.setOrientationLeft();
        onView(withId(filterId))
                .check(matches(isChecked()));
        onView(allOf(withParent(withId(filterId)), instanceOf(EditText.class)))
                .check(matches(isEnabled()));

        for (int id : IDS) {
            if (id != filterId) {
                onView(withId(id)).check(matches(isNotChecked()));
            }
        }
    }
}

FilterCards

public class FilterCards extends Fragment {
    private static final String INPUT_EXTRA = "input";

    private static final String[] EXTRAS = {BRAND_EXTRA, YEAR_EXTRA, NUMBER_EXTRA,
            PLAYER_NAME_EXTRA, TEAM_EXTRA};

    @InjectViews({R.id.brand, R.id.year, R.id.number, R.id.player_name, R.id.team})
    List<FilterOptionView> filterOptions;
    private ArrayList<Integer> enabledFields = new ArrayList<>();

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

        // restore input fields state
        if (savedInstanceState != null) {
            ArrayList<Integer> enabledFields = savedInstanceState
                    .getIntegerArrayList(INPUT_EXTRA);

            Log.d(TAG, "enabledField=" + enabledFields);

            if (enabledFields != null) {
                for (int i : enabledFields) {
                    filterOptions.get(i).setChecked(true);
                }
            }
        }

        return view;
    }

    @Override
    public void onPause() {
        super.onPause();

        enabledFields.clear();
        for (int i = 0; i < filterOptions.size(); i++) {
            if (filterOptions.get(i).isChecked()) {
                enabledFields.add(i);
            }
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        outState.putIntegerArrayList(INPUT_EXTRA, enabledFields);
    }
}

FilterOptionView

public class FilterOptionView extends CheckableLinearLayout {
    private TextView label;
    private EditText edit;

    public FilterOptionView(Context context) {
        this(context, null);
    }

    public FilterOptionView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FilterOptionView(final Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        label = new TextView(context);
        edit = new EditText(context);

        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.FilterOptionView,
                0, 0);
        int[] set = {android.R.attr.enabled, android.R.attr.inputType, android.R.attr.singleLine};
        TypedArray b = context.getTheme().obtainStyledAttributes(attrs, set, 0, 0);

        try {
            boolean enabled = a.getBoolean(0, true);
            mCheckBox.setChecked(enabled);
            label.setEnabled(enabled);
            edit.setEnabled(enabled);

            int labelWeight = a.getInt(R.styleable.FilterOptionView_labelWeight, 0);
            ViewGroup.LayoutParams labelParams = new LinearLayout.LayoutParams(
                    0, LayoutParams.WRAP_CONTENT, labelWeight);
            label.setLayoutParams(labelParams);

            int editWeight = a.getInt(R.styleable.FilterOptionView_editWeight, 0);
            ViewGroup.LayoutParams editParams = new LinearLayout.LayoutParams(
                    0, LayoutParams.WRAP_CONTENT, editWeight);
            edit.setLayoutParams(editParams);

            label.setText(a.getString(R.styleable.FilterOptionView_label));
            label.setTextSize(a.getDimension(R.styleable.FilterOptionView_labelTextSize, 1.0f));
            edit.setHint(a.getString(R.styleable.FilterOptionView_hint));
            edit.setInputType(b.getInt(1, 0));
            edit.setSingleLine(b.getBoolean(2, true));
        } finally {
            a.recycle();
        }

        this.addView(label);
        this.addView(edit);

        mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                label.setEnabled(isChecked);
                edit.setEnabled(isChecked);
                edit.requestFocus();

                // TODO: Should not be the responsibility of FilterOptionView
                if (context instanceof ActionBarActivity) {
                    ((ActionBarActivity) context).supportInvalidateOptionsMenu();
                }
            }
        });
    }

    @Override
    public void setChecked(boolean checked) {
        super.setChecked(checked);

        label.setEnabled(checked);
        edit.setEnabled(checked);
        edit.requestFocus();
    }

    public Editable getText() {
        return edit.getText();
    }
}

CheckableLinearLayout

public class CheckableLinearLayout extends LinearLayout implements Checkable {
    @InjectView(R.id.checkmark) CheckBox mCheckBox;

    public CheckableLinearLayout(Context context) {
        this(context, null);
    }

    public CheckableLinearLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CheckableLinearLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        View root = View.inflate(context, R.layout.checkable_linear_layout, this);
        ButterKnife.inject(this, root);
    }

    public void setChecked(boolean checked) {
        mCheckBox.setChecked(checked);
    }

    public boolean isChecked() {
        return mCheckBox.isChecked();
    }

    @Override
    public void toggle() {
        mCheckBox.toggle();
    }
}

0 个答案:

没有答案