[MaterialDatePicker] Added a DateValidator for a bounded range.

Resolves https://github.com/material-components/material-components-android/pull/972

GIT_ORIGIN_REV_ID=29cbbd569f5284f0bdf4cc1bdad60f93f92856eb

Co-authored-by: ymarian <38727469+ymarian@users.noreply.github.com>
PiperOrigin-RevId: 295810824
This commit is contained in:
Felipe Roriz 2020-02-18 16:38:35 -05:00 committed by ymarian
parent c589d8df7d
commit 4ccb052d2b
5 changed files with 206 additions and 5 deletions

View File

@ -30,11 +30,14 @@ import android.widget.LinearLayout;
import android.widget.RadioGroup;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.datepicker.CalendarConstraints;
import com.google.android.material.datepicker.CompositeDateValidator;
import com.google.android.material.datepicker.DateValidatorPointForward;
import com.google.android.material.datepicker.MaterialDatePicker;
import com.google.android.material.snackbar.Snackbar;
import io.material.catalog.feature.DemoFragment;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.TimeZone;
/** A fragment that displays the main Picker demos for the Catalog app. */
@ -190,6 +193,16 @@ public class DatePickerMainDemoFragment extends DemoFragment {
constraintsBuilder.setValidator(DateValidatorPointForward.now());
} else if (validationChoice == R.id.cat_picker_validation_weekdays) {
constraintsBuilder.setValidator(new DateValidatorWeekdays());
} else if ((validationChoice == R.id.cat_picker_validation_last_two_weeks)) {
Calendar lowerBoundCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
lowerBoundCalendar.add(Calendar.DAY_OF_MONTH, -14);
long lowerBound = lowerBoundCalendar.getTimeInMillis();
List<CalendarConstraints.DateValidator> validators = new ArrayList<>();
validators.add(DateValidatorPointForward.from(lowerBound));
validators.add(new DateValidatorWeekdays());
constraintsBuilder.setValidator(CompositeDateValidator.allOf(validators));
}
return constraintsBuilder;
}

View File

@ -33,7 +33,7 @@
android:id="@+id/cat_picker_validation_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="vertical">
<RadioButton
android:id="@+id/cat_picker_validation_default"
android:layout_width="wrap_content"
@ -45,18 +45,20 @@
android:id="@+id/cat_picker_validation_today_onward"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/cat_picker_demo_padding"
android:layout_marginLeft="@dimen/cat_picker_demo_padding"
android:text="@string/cat_picker_validation_today_onward"
android:textAppearance="?attr/textAppearanceBody1"/>
<RadioButton
android:id="@+id/cat_picker_validation_weekdays"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/cat_picker_demo_padding"
android:layout_marginLeft="@dimen/cat_picker_demo_padding"
android:text="@string/cat_picker_validation_weekdays"
android:textAppearance="?attr/textAppearanceBody1"/>
<RadioButton
android:id="@+id/cat_picker_validation_last_two_weeks"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cat_picker_validation_last_two_weeks"
android:textAppearance="?attr/textAppearanceBody1"/>
</RadioGroup>
</LinearLayout>

View File

@ -65,6 +65,8 @@
<string name="cat_picker_validation_today_onward">Today onward</string>
<!-- Indicates that only weekdays will be valid [CHAR LIMIT=25] -->
<string name="cat_picker_validation_weekdays">Weekdays</string>
<!-- Indicates that only the last 2 weeks will be valid [CHAR LIMIT=25] -->
<string name="cat_picker_validation_last_two_weeks">Last 2 weeks</string>
<!-- Grouping label for a set of radio buttons that choose the title [CHAR LIMIT=50] -->
<string name="cat_picker_title">Picker Title</string>

View File

@ -0,0 +1,113 @@
/*
* Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.material.datepicker;
import static androidx.core.util.Preconditions.checkNotNull;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import com.google.android.material.datepicker.CalendarConstraints.DateValidator;
import java.util.List;
/** A {@link DateValidator} that accepts a list of Date Validators. */
public final class CompositeDateValidator implements DateValidator {
@NonNull private final List<DateValidator> validators;
private CompositeDateValidator(@NonNull List<DateValidator> validators) {
this.validators = validators;
}
/**
* Returns a {@link DateValidator} that can perform validation for every given {@link
* #validators}.
*/
@NonNull
public static DateValidator allOf(@NonNull List<DateValidator> validators) {
return new CompositeDateValidator(validators);
}
/** Part of {@link Parcelable} requirements. Do not use. */
public static final Creator<CompositeDateValidator> CREATOR =
new Creator<CompositeDateValidator>() {
@NonNull
@Override
public CompositeDateValidator createFromParcel(@NonNull Parcel source) {
@SuppressWarnings("unchecked")
List<DateValidator> validators =
source.readArrayList(DateValidator.class.getClassLoader());
return new CompositeDateValidator(checkNotNull(validators));
}
@NonNull
@Override
public CompositeDateValidator[] newArray(int size) {
return new CompositeDateValidator[size];
}
};
/**
* Performs the {@link DateValidator#isValid(long)} check as an AND of all validators in {@link
* #validators}. e.g. If every validator in this class returns `true` for each {@link
* DateValidator#isValid(long)}, this this method will return true.
*
* @param date milliseconds date to validate against.
* @return True, if the given date is valid for every given validator in this class.
*/
@Override
public boolean isValid(long date) {
for (DateValidator validator : validators) {
if (validator == null) {
continue;
}
if (!validator.isValid(date)) {
return false;
}
}
return true;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeList(validators);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof CompositeDateValidator)) {
return false;
}
CompositeDateValidator that = (CompositeDateValidator) o;
return validators.equals(that.validators);
}
@Override
public int hashCode() {
return validators.hashCode();
}
}

View File

@ -0,0 +1,71 @@
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.material.datepicker;
import com.google.android.material.R;
import static com.google.common.truth.Truth.assertThat;
import android.os.Parcel;
import com.google.android.material.datepicker.CalendarConstraints.DateValidator;
import java.util.ArrayList;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
/** Test for {@link CompositeDateValidator} */
@RunWith(RobolectricTestRunner.class)
public class CompositeDateValidatorTest {
private DateValidator subject;
@Before
public void createSubject() {
DateValidator validator1 = DateValidatorPointBackward.before(5);
DateValidator validator2 = DateValidatorPointForward.from(2);
ArrayList<DateValidator> validators = new ArrayList<>(2);
validators.add(validator1);
validators.add(validator2);
subject = CompositeDateValidator.allOf(validators);
}
@Test
public void testValidDate() {
assertThat(subject.isValid(4)).isTrue();
}
@Test
public void testInvalidDate() {
assertThat(subject.isValid(1)).isFalse();
assertThat(subject.isValid(6)).isFalse();
}
@Test
public void testParcelable() {
DateValidator original = subject;
Parcel parcel = Parcel.obtain();
original.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
DateValidator createdFromParcel = CompositeDateValidator.CREATOR.createFromParcel(parcel);
assertThat(original).isEqualTo(createdFromParcel);
}
}