Skip to content

Commit 4ccb052

Browse files
froriz5ymarian
andcommitted
[MaterialDatePicker] Added a DateValidator for a bounded range.
Resolves #972 GIT_ORIGIN_REV_ID=29cbbd569f5284f0bdf4cc1bdad60f93f92856eb Co-authored-by: ymarian <[email protected]> PiperOrigin-RevId: 295810824
1 parent c589d8d commit 4ccb052

File tree

5 files changed

+206
-5
lines changed

5 files changed

+206
-5
lines changed

catalog/java/io/material/catalog/datepicker/DatePickerMainDemoFragment.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,14 @@
3030
import android.widget.RadioGroup;
3131
import com.google.android.material.button.MaterialButton;
3232
import com.google.android.material.datepicker.CalendarConstraints;
33+
import com.google.android.material.datepicker.CompositeDateValidator;
3334
import com.google.android.material.datepicker.DateValidatorPointForward;
3435
import com.google.android.material.datepicker.MaterialDatePicker;
3536
import com.google.android.material.snackbar.Snackbar;
3637
import io.material.catalog.feature.DemoFragment;
38+
import java.util.ArrayList;
3739
import java.util.Calendar;
40+
import java.util.List;
3841
import java.util.TimeZone;
3942

4043
/** A fragment that displays the main Picker demos for the Catalog app. */
@@ -190,6 +193,16 @@ private CalendarConstraints.Builder setupConstraintsBuilder(
190193
constraintsBuilder.setValidator(DateValidatorPointForward.now());
191194
} else if (validationChoice == R.id.cat_picker_validation_weekdays) {
192195
constraintsBuilder.setValidator(new DateValidatorWeekdays());
196+
} else if ((validationChoice == R.id.cat_picker_validation_last_two_weeks)) {
197+
Calendar lowerBoundCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
198+
lowerBoundCalendar.add(Calendar.DAY_OF_MONTH, -14);
199+
long lowerBound = lowerBoundCalendar.getTimeInMillis();
200+
201+
List<CalendarConstraints.DateValidator> validators = new ArrayList<>();
202+
validators.add(DateValidatorPointForward.from(lowerBound));
203+
validators.add(new DateValidatorWeekdays());
204+
205+
constraintsBuilder.setValidator(CompositeDateValidator.allOf(validators));
193206
}
194207
return constraintsBuilder;
195208
}

catalog/java/io/material/catalog/datepicker/res/layout/cat_picker_validation.xml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
android:id="@+id/cat_picker_validation_group"
3434
android:layout_width="match_parent"
3535
android:layout_height="wrap_content"
36-
android:orientation="horizontal">
36+
android:orientation="vertical">
3737
<RadioButton
3838
android:id="@+id/cat_picker_validation_default"
3939
android:layout_width="wrap_content"
@@ -45,18 +45,20 @@
4545
android:id="@+id/cat_picker_validation_today_onward"
4646
android:layout_width="wrap_content"
4747
android:layout_height="wrap_content"
48-
android:layout_marginStart="@dimen/cat_picker_demo_padding"
49-
android:layout_marginLeft="@dimen/cat_picker_demo_padding"
5048
android:text="@string/cat_picker_validation_today_onward"
5149
android:textAppearance="?attr/textAppearanceBody1"/>
5250
<RadioButton
5351
android:id="@+id/cat_picker_validation_weekdays"
5452
android:layout_width="wrap_content"
5553
android:layout_height="wrap_content"
56-
android:layout_marginStart="@dimen/cat_picker_demo_padding"
57-
android:layout_marginLeft="@dimen/cat_picker_demo_padding"
5854
android:text="@string/cat_picker_validation_weekdays"
5955
android:textAppearance="?attr/textAppearanceBody1"/>
56+
<RadioButton
57+
android:id="@+id/cat_picker_validation_last_two_weeks"
58+
android:layout_width="wrap_content"
59+
android:layout_height="wrap_content"
60+
android:text="@string/cat_picker_validation_last_two_weeks"
61+
android:textAppearance="?attr/textAppearanceBody1"/>
6062

6163
</RadioGroup>
6264
</LinearLayout>

catalog/java/io/material/catalog/datepicker/res/values/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@
6565
<string name="cat_picker_validation_today_onward">Today onward</string>
6666
<!-- Indicates that only weekdays will be valid [CHAR LIMIT=25] -->
6767
<string name="cat_picker_validation_weekdays">Weekdays</string>
68+
<!-- Indicates that only the last 2 weeks will be valid [CHAR LIMIT=25] -->
69+
<string name="cat_picker_validation_last_two_weeks">Last 2 weeks</string>
6870

6971
<!-- Grouping label for a set of radio buttons that choose the title [CHAR LIMIT=50] -->
7072
<string name="cat_picker_title">Picker Title</string>
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
* Copyright 2019 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.google.android.material.datepicker;
17+
18+
import static androidx.core.util.Preconditions.checkNotNull;
19+
20+
import android.os.Parcel;
21+
import android.os.Parcelable;
22+
import androidx.annotation.NonNull;
23+
import com.google.android.material.datepicker.CalendarConstraints.DateValidator;
24+
import java.util.List;
25+
26+
/** A {@link DateValidator} that accepts a list of Date Validators. */
27+
public final class CompositeDateValidator implements DateValidator {
28+
29+
@NonNull private final List<DateValidator> validators;
30+
31+
private CompositeDateValidator(@NonNull List<DateValidator> validators) {
32+
this.validators = validators;
33+
}
34+
35+
/**
36+
* Returns a {@link DateValidator} that can perform validation for every given {@link
37+
* #validators}.
38+
*/
39+
@NonNull
40+
public static DateValidator allOf(@NonNull List<DateValidator> validators) {
41+
return new CompositeDateValidator(validators);
42+
}
43+
44+
/** Part of {@link Parcelable} requirements. Do not use. */
45+
public static final Creator<CompositeDateValidator> CREATOR =
46+
new Creator<CompositeDateValidator>() {
47+
@NonNull
48+
@Override
49+
public CompositeDateValidator createFromParcel(@NonNull Parcel source) {
50+
@SuppressWarnings("unchecked")
51+
List<DateValidator> validators =
52+
source.readArrayList(DateValidator.class.getClassLoader());
53+
return new CompositeDateValidator(checkNotNull(validators));
54+
}
55+
56+
@NonNull
57+
@Override
58+
public CompositeDateValidator[] newArray(int size) {
59+
return new CompositeDateValidator[size];
60+
}
61+
};
62+
63+
/**
64+
* Performs the {@link DateValidator#isValid(long)} check as an AND of all validators in {@link
65+
* #validators}. e.g. If every validator in this class returns `true` for each {@link
66+
* DateValidator#isValid(long)}, this this method will return true.
67+
*
68+
* @param date milliseconds date to validate against.
69+
* @return True, if the given date is valid for every given validator in this class.
70+
*/
71+
@Override
72+
public boolean isValid(long date) {
73+
for (DateValidator validator : validators) {
74+
if (validator == null) {
75+
continue;
76+
}
77+
if (!validator.isValid(date)) {
78+
return false;
79+
}
80+
}
81+
return true;
82+
}
83+
84+
@Override
85+
public int describeContents() {
86+
return 0;
87+
}
88+
89+
@Override
90+
public void writeToParcel(@NonNull Parcel dest, int flags) {
91+
dest.writeList(validators);
92+
}
93+
94+
@Override
95+
public boolean equals(Object o) {
96+
if (this == o) {
97+
return true;
98+
}
99+
100+
if (!(o instanceof CompositeDateValidator)) {
101+
return false;
102+
}
103+
104+
CompositeDateValidator that = (CompositeDateValidator) o;
105+
106+
return validators.equals(that.validators);
107+
}
108+
109+
@Override
110+
public int hashCode() {
111+
return validators.hashCode();
112+
}
113+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright 2020 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.android.material.datepicker;
18+
19+
import com.google.android.material.R;
20+
21+
import static com.google.common.truth.Truth.assertThat;
22+
23+
import android.os.Parcel;
24+
import com.google.android.material.datepicker.CalendarConstraints.DateValidator;
25+
import java.util.ArrayList;
26+
import org.junit.Before;
27+
import org.junit.Test;
28+
import org.junit.runner.RunWith;
29+
import org.robolectric.RobolectricTestRunner;
30+
31+
/** Test for {@link CompositeDateValidator} */
32+
@RunWith(RobolectricTestRunner.class)
33+
public class CompositeDateValidatorTest {
34+
35+
private DateValidator subject;
36+
37+
@Before
38+
public void createSubject() {
39+
DateValidator validator1 = DateValidatorPointBackward.before(5);
40+
DateValidator validator2 = DateValidatorPointForward.from(2);
41+
42+
ArrayList<DateValidator> validators = new ArrayList<>(2);
43+
validators.add(validator1);
44+
validators.add(validator2);
45+
46+
subject = CompositeDateValidator.allOf(validators);
47+
}
48+
49+
@Test
50+
public void testValidDate() {
51+
assertThat(subject.isValid(4)).isTrue();
52+
}
53+
54+
@Test
55+
public void testInvalidDate() {
56+
assertThat(subject.isValid(1)).isFalse();
57+
assertThat(subject.isValid(6)).isFalse();
58+
}
59+
60+
@Test
61+
public void testParcelable() {
62+
DateValidator original = subject;
63+
64+
Parcel parcel = Parcel.obtain();
65+
original.writeToParcel(parcel, 0);
66+
parcel.setDataPosition(0);
67+
68+
DateValidator createdFromParcel = CompositeDateValidator.CREATOR.createFromParcel(parcel);
69+
assertThat(original).isEqualTo(createdFromParcel);
70+
}
71+
}

0 commit comments

Comments
 (0)