Skip to content

Commit 6ca57f5

Browse files
authored
Merge pull request #84 from huttneab/bug_fixes_3
Fix a big UI bug for save instance state.
2 parents 1f4d5a8 + f0894cc commit 6ca57f5

10 files changed

Lines changed: 132 additions & 27 deletions

File tree

app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Manifest version information!
22
def versionMajor = 1
33
def versionMinor = 0
4-
def versionPatch = 7
4+
def versionPatch = 8
55
def versionBuild = 0 // bump for dogfood builds, public betas, etc.
66

77
apply plugin: 'com.android.application'

app/src/main/java/com/rockthevote/grommet/data/api/model/ApiAddress.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ public void toJson(JsonWriter writer, ApiAddress value) throws IOException {
134134
writer.beginObject();
135135
writer.name("sub_address_type");
136136
writer.value("APT");
137-
writer.name("subAddress");
137+
writer.name("sub_address");
138138
subAddressAdapter.toJson(writer, value.subAddress());
139139
writer.endObject();
140140

app/src/main/java/com/rockthevote/grommet/ui/misc/BetterSpinner.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
package com.rockthevote.grommet.ui.misc;
22

33
import android.content.Context;
4+
import android.os.Bundle;
5+
import android.os.Parcelable;
46
import android.support.annotation.NonNull;
57
import android.support.design.widget.TextInputEditText;
68
import android.support.design.widget.TextInputLayout;
79
import android.support.v7.widget.ListPopupWindow;
810
import android.util.AttributeSet;
11+
import android.util.SparseArray;
912
import android.widget.AdapterView;
1013
import android.widget.ListAdapter;
1114

1215
import com.rockthevote.grommet.R;
1316

1417

1518
public class BetterSpinner extends TextInputLayout {
19+
private String childrenStateKey;
20+
private String superStateKey;
1621

1722
ListPopupWindow listPopupWindow;
1823
ListAdapter listAdapter;
@@ -29,6 +34,10 @@ public BetterSpinner(Context context, AttributeSet attrs) {
2934
public BetterSpinner(Context context, AttributeSet attrs, int defStyleAttr) {
3035
super(context, attrs, defStyleAttr);
3136

37+
superStateKey = BetterSpinner.class.getSimpleName() + ".superState";
38+
childrenStateKey = BetterSpinner.class.getSimpleName() + ".childState";
39+
40+
3241
editText = new TextInputEditText(context);
3342
editText.setId(R.id.titleId);
3443
editText.setHeight((int) getResources().getDimension(R.dimen.list_item_height));
@@ -64,6 +73,46 @@ public void setHeight(int height) {
6473
listPopupWindow.setHeight(height);
6574
}
6675

76+
@Override
77+
public Parcelable onSaveInstanceState() {
78+
final Bundle state = new Bundle();
79+
state.putParcelable(superStateKey, super.onSaveInstanceState());
80+
state.putSparseParcelableArray(childrenStateKey,
81+
ChildrenViewStateHelper.newInstance(this).saveChildrenState(childrenStateKey));
82+
return state;
83+
}
84+
85+
@Override
86+
protected void onRestoreInstanceState(final Parcelable state) {
87+
if (state instanceof Bundle) {
88+
final Bundle localState = (Bundle) state;
89+
super.onRestoreInstanceState(localState.getParcelable(superStateKey));
90+
ChildrenViewStateHelper.newInstance(this).restoreChildrenState(localState
91+
.getSparseParcelableArray(childrenStateKey), childrenStateKey);
92+
} else {
93+
super.onRestoreInstanceState(state);
94+
}
95+
}
96+
97+
@Override
98+
protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
99+
dispatchFreezeSelfOnly(container);
100+
}
101+
102+
@Override
103+
protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
104+
dispatchThawSelfOnly(container);
105+
}
106+
107+
@Override
108+
public void setEnabled(boolean enabled) {
109+
super.setEnabled(enabled);
110+
if (!enabled) {
111+
getEditText().setText("");
112+
}
113+
getEditText().setEnabled(enabled);
114+
}
115+
67116
@NonNull
68117
@Override
69118
public TextInputEditText getEditText() {

app/src/main/java/com/rockthevote/grommet/ui/misc/ChildrenViewStateHelper.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,16 @@ private ChildrenViewStateHelper() {
2525
* Also you need override {@link ViewGroup#dispatchSaveInstanceState(SparseArray)} and call {@link ViewGroup#dispatchFreezeSelfOnly(SparseArray)}.
2626
*/
2727
public SparseArray<Parcelable> saveChildrenState() {
28+
return saveChildrenState(DEFAULT_CHILDREN_STATE_KEY);
29+
}
30+
31+
public SparseArray<Parcelable> saveChildrenState(String stateKey) {
2832
final SparseArray<Parcelable> array = new SparseArray<>();
2933
for (int i = 0; i < mClientViewGroup.getChildCount(); i++) {
3034
final Bundle bundle = new Bundle();
3135
final SparseArray<Parcelable> childArray = new SparseArray<>(); //create independent SparseArray for each child (View or ViewGroup)
3236
mClientViewGroup.getChildAt(i).saveHierarchyState(childArray);
33-
bundle.putSparseParcelableArray(DEFAULT_CHILDREN_STATE_KEY, childArray);
37+
bundle.putSparseParcelableArray(stateKey, childArray);
3438
array.append(i, bundle);
3539
}
3640
return array;
@@ -41,12 +45,16 @@ public SparseArray<Parcelable> saveChildrenState() {
4145
* Also you need override {@link ViewGroup#dispatchRestoreInstanceState(SparseArray)} and call {@link ViewGroup#dispatchThawSelfOnly(SparseArray)}.
4246
*/
4347
public void restoreChildrenState(@Nullable final SparseArray<Parcelable> childrenState) {
48+
restoreChildrenState(childrenState, DEFAULT_CHILDREN_STATE_KEY);
49+
}
50+
51+
public void restoreChildrenState(@Nullable final SparseArray<Parcelable> childrenState, String stateKey) {
4452
if (null == childrenState) {
4553
return;
4654
}
4755
for (int i = 0; i < mClientViewGroup.getChildCount(); i++) {
4856
final Bundle bundle = (Bundle) childrenState.get(i);
49-
final SparseArray<Parcelable> childState = bundle.getSparseParcelableArray(DEFAULT_CHILDREN_STATE_KEY);
57+
final SparseArray<Parcelable> childState = bundle.getSparseParcelableArray(stateKey);
5058
mClientViewGroup.getChildAt(i).restoreHierarchyState(childState);
5159
}
5260
}

app/src/main/java/com/rockthevote/grommet/ui/misc/StepperTabLayout.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,20 +65,25 @@ public void enableTabAtPosition(int pos) {
6565
@Override
6666
protected Parcelable onSaveInstanceState() {
6767
final Bundle state = new Bundle();
68-
state.putParcelable("superState", super.onSaveInstanceState());
68+
state.putParcelable("stepperSuperState", super.onSaveInstanceState());
6969
state.putParcelable(STEPPER_STATE_KEY, new SparseBooleanArrayParcelable(enabled));
7070
return state;
7171
}
7272

7373
@Override
74+
@SuppressWarnings("ConstantConditions")
7475
protected void onRestoreInstanceState(final Parcelable state) {
7576
if (state instanceof Bundle) {
7677
final Bundle localState = (Bundle) state;
77-
super.onRestoreInstanceState(localState.getParcelable("superState"));
78+
super.onRestoreInstanceState(localState.getParcelable("stepperSuperState"));
7879
enabled = localState.getParcelable(STEPPER_STATE_KEY);
80+
for (int i = 0; i < getTabCount(); i++) {
81+
getTabAt(i).getCustomView().setEnabled(enabled.get(i));
82+
}
7983
} else {
8084
super.onRestoreInstanceState(state);
8185
}
8286
}
8387

88+
8489
}

app/src/main/java/com/rockthevote/grommet/ui/registration/AdditionalInfoFragment.java

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
import static com.rockthevote.grommet.data.db.model.VoterId.Type.SSN_LAST_FOUR;
5454

5555
public class AdditionalInfoFragment extends BaseRegistrationFragment {
56+
private static final String OTHER_PARTY_VISIBILITY_KEY = "other_party_visibility_key";
5657

5758
@BindView(R.id.spinner_race) BetterSpinner raceSpinner;
5859

@@ -131,15 +132,13 @@ public void onViewCreated(View view, Bundle savedInstanceState) {
131132

132133
validator = new ObservableValidator(this, getActivity());
133134

134-
135135
// Setup Race Spinner
136136
raceEnumAdapter = new EnumAdapter<>(getActivity(), Race.class);
137137
raceSpinner.setAdapter(raceEnumAdapter);
138138
raceSpinner.setOnItemClickListener((adapterView, view1, i, l) -> {
139139
raceSpinner.getEditText().setText(raceEnumAdapter.getItem(i).toString());
140140
raceSpinner.dismiss();
141141
});
142-
raceSpinner.getEditText().setText(Race.OTHER.toString());
143142

144143

145144
// Setup Party Spinner
@@ -168,12 +167,24 @@ public void onViewCreated(View view, Bundle savedInstanceState) {
168167
phoneTypeSpinner.getEditText().setText(phoneTypeEnumAdapter.getItem(i).toString());
169168
phoneTypeSpinner.dismiss();
170169
});
171-
phoneTypeSpinner.getEditText().setText(phoneTypeEnumAdapter.getItem(0).toString());
170+
171+
if (null != savedInstanceState) {
172+
otherPartyTIL.setVisibility(savedInstanceState.getBoolean(OTHER_PARTY_VISIBILITY_KEY) ?
173+
View.VISIBLE : View.GONE);
174+
}
175+
172176
}
173177

174178
@Override
175179
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
176180
super.onActivityCreated(savedInstanceState);
181+
182+
// set up defaults
183+
if (null == savedInstanceState) {
184+
raceSpinner.getEditText().setText(Race.OTHER.toString());
185+
phoneTypeSpinner.getEditText().setText(phoneTypeEnumAdapter.getItem(0).toString());
186+
}
187+
177188
phoneOptIn.setText(getString(R.string.label_receive_text, partnerNamePref.get()));
178189
emailOptIn.setText(getString(R.string.label_receive_email, partnerNamePref.get()));
179190
}
@@ -222,7 +233,6 @@ public void onResume() {
222233
subscriptions.add(RxTextView.afterTextChangeEvents(preferredLanguage)
223234
.observeOn(Schedulers.io())
224235
.debounce(DEBOUNCE, TimeUnit.MILLISECONDS)
225-
.skip(1)
226236
.subscribe(event -> {
227237
AdditionalInfo.insertOrUpdate(db, rockyRequestRowId.get(),
228238
LANGUAGE_PREF, new AdditionalInfo.Builder()
@@ -356,6 +366,12 @@ public void onSSNChecked(boolean checked) {
356366
doesNotHaveSSN.onNext(checked);
357367
}
358368

369+
@Override
370+
public void onSaveInstanceState(Bundle outState) {
371+
outState.putBoolean(OTHER_PARTY_VISIBILITY_KEY, View.VISIBLE == otherPartyTIL.getVisibility());
372+
super.onSaveInstanceState(outState);
373+
}
374+
359375
@Override
360376
public Observable<Boolean> verify() {
361377
return validator.validate();

app/src/main/java/com/rockthevote/grommet/ui/registration/ReviewAndConfirmFragment.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,15 @@ public void onAcceptClick() {
137137
.subscribe(rockyRequest -> {
138138
birthday.setText(Dates.formatAsISO8601_ShortDate(rockyRequest.dateOfBirth()));
139139
race.setText(rockyRequest.race().toString());
140-
party.setText(rockyRequest.party().toString());
140+
141+
String polParty;
142+
if (RockyRequest.Party.OTHER_PARTY == rockyRequest.party()) {
143+
polParty = rockyRequest.otherParty();
144+
} else {
145+
polParty = rockyRequest.party().toString();
146+
}
147+
148+
party.setText(polParty);
141149
phoneLabel.setText(rockyRequest.phoneType().toString());
142150
// show/hide registration address views
143151
for (View v : mailingAddressViews) {
@@ -187,6 +195,8 @@ public void onClearSignatureClick(View v) {
187195
public void onCheckChanged(boolean checked) {
188196
if (checked) {
189197
dialog.show(getFragmentManager(), "disclosure_dialog");
198+
} else {
199+
buttonRegister.setEnabled(false);
190200
}
191201
}
192202

@@ -198,7 +208,8 @@ public void onStartSigning() {
198208
@Override
199209
public void onSigned() {
200210
ByteArrayOutputStream baos = new ByteArrayOutputStream();
201-
Bitmap image = (Images.aspectSafeScale(Images.transformAspectRatio(signaturePad.getSignatureBitmap(), 3, 1), 180, 60));
211+
Bitmap image = Images.transformAspectRatio(signaturePad.getSignatureBitmap(), 3, 1);
212+
image = Images.aspectSafeScale(image, 180, 60);
202213
image.compress(Bitmap.CompressFormat.PNG, 100, baos);
203214

204215
db.update(RockyRequest.TABLE,

app/src/main/java/com/rockthevote/grommet/ui/views/AddressView.java

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.rockthevote.grommet.ui.misc.BetterSpinner;
2525
import com.rockthevote.grommet.ui.misc.ChildrenViewStateHelper;
2626
import com.rockthevote.grommet.ui.misc.ObservableValidator;
27+
import com.rockthevote.grommet.util.Strings;
2728
import com.squareup.sqlbrite.BriteDatabase;
2829

2930
import java.util.concurrent.TimeUnit;
@@ -41,6 +42,11 @@
4142
public class AddressView extends FrameLayout {
4243
private static final String PA_ABREV = "PA";
4344

45+
private static final String COUNTY_ENABLED_KEY = "county_enabled_key";
46+
47+
private String childrenStateKey;
48+
private String superStateKey;
49+
4450
@NotEmpty
4551
@BindView(R.id.til_street_address) TextInputLayout streetTIL;
4652
@BindView(R.id.street) EditText streetEditText;
@@ -112,10 +118,14 @@ public AddressView(Context context, AttributeSet attrs, int defStyleAttr) {
112118
break;
113119
case 4:
114120
type = Address.Type.ASSISTANT_ADDRESS;
121+
break;
115122
}
116123
} finally {
117124
typedArray.recycle();
118125
}
126+
127+
superStateKey = AddressView.class.getSimpleName() + ".superState." + type.toString();
128+
childrenStateKey = AddressView.class.getSimpleName() + ".childState." + type.toString();
119129
}
120130
}
121131

@@ -163,16 +173,15 @@ protected void onFinishInflate() {
163173
if (!PA_ABREV.equals(stateAdapter.getItem(i))) {
164174
countySpinner.setErrorEnabled(false);
165175
countySpinner.setEnabled(false);
166-
countySpinner.getEditText().setText("");
167-
countySpinner.getEditText().setEnabled(false);
168176
} else {
169-
countySpinner.getEditText().setEnabled(true);
170177
countySpinner.setEnabled(true);
171178
}
172179

173180
stateSpinner.dismiss();
174181
});
175-
stateSpinner.getEditText().setText(stateAdapter.getItem(stateAdapter.getPosition(PA_ABREV)));
182+
if (Strings.isBlank(stateSpinner.getEditText().getEditableText().toString())) {
183+
stateSpinner.getEditText().setText(stateAdapter.getItem(stateAdapter.getPosition(PA_ABREV)));
184+
}
176185
}
177186
}
178187

@@ -211,19 +220,21 @@ protected void onDetachedFromWindow() {
211220
@Override
212221
protected Parcelable onSaveInstanceState() {
213222
final Bundle state = new Bundle();
214-
state.putParcelable("superState", super.onSaveInstanceState());
215-
state.putSparseParcelableArray(ChildrenViewStateHelper.DEFAULT_CHILDREN_STATE_KEY,
216-
ChildrenViewStateHelper.newInstance(this).saveChildrenState());
223+
state.putParcelable(superStateKey, super.onSaveInstanceState());
224+
state.putBoolean(COUNTY_ENABLED_KEY, countySpinner.isEnabled());
225+
state.putSparseParcelableArray(childrenStateKey,
226+
ChildrenViewStateHelper.newInstance(this).saveChildrenState(childrenStateKey));
217227
return state;
218228
}
219229

220230
@Override
221231
protected void onRestoreInstanceState(final Parcelable state) {
222232
if (state instanceof Bundle) {
223233
final Bundle localState = (Bundle) state;
224-
super.onRestoreInstanceState(localState.getParcelable("superState"));
234+
super.onRestoreInstanceState(localState.getParcelable(superStateKey));
225235
ChildrenViewStateHelper.newInstance(this).restoreChildrenState(localState
226-
.getSparseParcelableArray(ChildrenViewStateHelper.DEFAULT_CHILDREN_STATE_KEY));
236+
.getSparseParcelableArray(childrenStateKey), childrenStateKey);
237+
countySpinner.setEnabled(localState.getBoolean(COUNTY_ENABLED_KEY, true));
227238
} else {
228239
super.onRestoreInstanceState(state);
229240
}

app/src/main/java/com/rockthevote/grommet/ui/views/NameView.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@
4141

4242
public class NameView extends FrameLayout {
4343

44+
private String childrenStateKey;
45+
private String superStateKey;
46+
4447
@BindView(R.id.name_section_title) TextView sectionTitle;
4548

4649
@NotEmpty
@@ -108,7 +111,8 @@ public NameView(Context context, AttributeSet attrs, int defStyleAttr) {
108111
} finally {
109112
typedArray.recycle();
110113
}
111-
114+
superStateKey = NameView.class.getSimpleName() + ".superState." + type.toString();
115+
childrenStateKey = NameView.class.getSimpleName() + ".childState." + type.toString();
112116
}
113117
}
114118

@@ -182,19 +186,19 @@ protected void onDetachedFromWindow() {
182186
@Override
183187
protected Parcelable onSaveInstanceState() {
184188
final Bundle state = new Bundle();
185-
state.putParcelable("superState", super.onSaveInstanceState());
186-
state.putSparseParcelableArray(ChildrenViewStateHelper.DEFAULT_CHILDREN_STATE_KEY,
187-
ChildrenViewStateHelper.newInstance(this).saveChildrenState());
189+
state.putParcelable(superStateKey, super.onSaveInstanceState());
190+
state.putSparseParcelableArray(childrenStateKey,
191+
ChildrenViewStateHelper.newInstance(this).saveChildrenState(childrenStateKey));
188192
return state;
189193
}
190194

191195
@Override
192196
protected void onRestoreInstanceState(final Parcelable state) {
193197
if (state instanceof Bundle) {
194198
final Bundle localState = (Bundle) state;
195-
super.onRestoreInstanceState(localState.getParcelable("superState"));
199+
super.onRestoreInstanceState(localState.getParcelable(superStateKey));
196200
ChildrenViewStateHelper.newInstance(this).restoreChildrenState(localState
197-
.getSparseParcelableArray(ChildrenViewStateHelper.DEFAULT_CHILDREN_STATE_KEY));
201+
.getSparseParcelableArray(childrenStateKey), childrenStateKey);
198202
} else {
199203
super.onRestoreInstanceState(state);
200204
}

0 commit comments

Comments
 (0)