diff --git a/dependencies.gradle b/dependencies.gradle index fef7f87e..fd80a2e3 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,18 +1,19 @@ ext { androidPlugin = 'com.android.tools.build:gradle:3.0.1' minSdkVersion = 14 - compileSdkVersion = 27 + compileSdkVersion = 28 kotlinPlugin = 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.21' kotlinStdlib = 'org.jetbrains.kotlin:kotlin-stdlib:1.2.21' kotlinPoet = 'com.squareup:kotlinpoet:0.6.0' - supportVersion = '27.0.2' + supportVersion = '28.0.0-alpha1' supportAnnotations = "com.android.support:support-annotations:$supportVersion" supportV4CoreUi = "com.android.support:support-core-ui:$supportVersion" supportRecyclerView = "com.android.support:recyclerview-v7:$supportVersion" supportAppCompat = "com.android.support:appcompat-v7:$supportVersion" supportDesign = "com.android.support:design:$supportVersion" + supportDesignChip = "com.android.support:design-chip:$supportVersion" supportLeanback = "com.android.support:leanback-v17:$supportVersion" autoValue = 'com.google.auto.value:auto-value:1.5.2' diff --git a/rxbinding-design-chip/.gitignore b/rxbinding-design-chip/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/rxbinding-design-chip/.gitignore @@ -0,0 +1 @@ +/build diff --git a/rxbinding-design-chip/build.gradle b/rxbinding-design-chip/build.gradle new file mode 100644 index 00000000..ad61bedb --- /dev/null +++ b/rxbinding-design-chip/build.gradle @@ -0,0 +1,57 @@ +buildscript { + dependencies { + classpath rootProject.ext.androidPlugin + } +} + +apply plugin: 'com.android.library' +apply plugin: 'rxbinding-module' + +dependencies { + api project(':rxbinding') + api rootProject.ext.supportDesignChip + implementation rootProject.ext.rxAndroid + implementation rootProject.ext.supportAnnotations + + compileOnly rootProject.ext.autoValueAnnotations + annotationProcessor rootProject.ext.autoValue + + androidTestImplementation project(':testing-utils') + androidTestImplementation rootProject.ext.supportTestRunner + androidTestImplementation rootProject.ext.supportTestRules + androidTestImplementation rootProject.ext.supportTestEspresso + androidTestImplementation rootProject.ext.rxAndroid +} + +android { + compileSdkVersion rootProject.ext.compileSdkVersion + + defaultConfig { + minSdkVersion rootProject.ext.minSdkVersion + + testInstrumentationRunner 'com.jakewharton.rxbinding.RxBindingTestRunner' + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + } + + lintOptions { + textReport true + textOutput 'stdout' + } + + buildTypes { + debug { + testCoverageEnabled true + } + } + + // TODO replace with https://issuetracker.google.com/issues/72050365 once released. + libraryVariants.all { + it.generateBuildConfig.enabled = false + } +} + +apply from: rootProject.file('gradle/gradle-mvn-push.gradle') diff --git a/rxbinding-design-chip/gradle.properties b/rxbinding-design-chip/gradle.properties new file mode 100644 index 00000000..957f4b11 --- /dev/null +++ b/rxbinding-design-chip/gradle.properties @@ -0,0 +1,3 @@ +POM_ARTIFACT_ID=rxbinding-design-chip +POM_NAME=RxBinding (design-chip) +POM_PACKAGING=aar diff --git a/rxbinding-design-chip/src/androidTest/java/com/jakewharton/rxbinding2/support/design/chip/RxChipGroupTest.java b/rxbinding-design-chip/src/androidTest/java/com/jakewharton/rxbinding2/support/design/chip/RxChipGroupTest.java new file mode 100644 index 00000000..5557a17d --- /dev/null +++ b/rxbinding-design-chip/src/androidTest/java/com/jakewharton/rxbinding2/support/design/chip/RxChipGroupTest.java @@ -0,0 +1,72 @@ +package com.jakewharton.rxbinding2.support.design.chip; + +import android.content.Context; +import android.support.design.chip.Chip; +import android.support.design.chip.ChipGroup; +import android.support.test.InstrumentationRegistry; +import android.support.test.annotation.UiThreadTest; +import android.support.test.rule.UiThreadTestRule; +import android.support.test.runner.AndroidJUnit4; +import android.support.v7.view.ContextThemeWrapper; +import android.view.View; + +import com.jakewharton.rxbinding2.RecordingObserver; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import io.reactivex.functions.Consumer; + +import static org.junit.Assert.assertEquals; + +@RunWith(AndroidJUnit4.class) +@SuppressWarnings("ResourceType") // Don't need real IDs for test case. +public final class RxChipGroupTest { + @Rule public final UiThreadTestRule uiThread = new UiThreadTestRule(); + + private final Context context = new ContextThemeWrapper(InstrumentationRegistry.getContext(), R.style.Theme_AppCompat); + private final ChipGroup view = new ChipGroup(context); + + @Before public void setUp() { + view.setSingleSelection(true); + Chip button1 = new Chip(context); + button1.setId(1); + view.addView(button1); + Chip button2 = new Chip(context); + button2.setId(2); + view.addView(button2); + } + + @Test @UiThreadTest public void checkedChanges() { + RecordingObserver o = new RecordingObserver<>(); + RxChipGroup.checkedChanges(view).subscribe(o); + assertEquals(View.NO_ID, o.takeNext().intValue()); + + view.check(1); + assertEquals(1, o.takeNext().intValue()); + + view.clearCheck(); + assertEquals(View.NO_ID, o.takeNext().intValue()); + + view.check(2); + assertEquals(2, o.takeNext().intValue()); + + o.dispose(); + + view.check(1); + o.assertNoMoreEvents(); + } + + @Test @UiThreadTest public void checked() throws Exception { + Consumer action = RxChipGroup.checked(view); + assertEquals(View.NO_ID, view.getCheckedChipId()); + action.accept(1); + assertEquals(1, view.getCheckedChipId()); + action.accept(View.NO_ID); + assertEquals(View.NO_ID, view.getCheckedChipId()); + action.accept(2); + assertEquals(2, view.getCheckedChipId()); + } +} diff --git a/rxbinding-design-chip/src/main/AndroidManifest.xml b/rxbinding-design-chip/src/main/AndroidManifest.xml new file mode 100644 index 00000000..dbfd5689 --- /dev/null +++ b/rxbinding-design-chip/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/rxbinding-design-chip/src/main/java/com/jakewharton/rxbinding2/support/design/chip/ChipGroupCheckedChangeObservable.java b/rxbinding-design-chip/src/main/java/com/jakewharton/rxbinding2/support/design/chip/ChipGroupCheckedChangeObservable.java new file mode 100644 index 00000000..bbc89617 --- /dev/null +++ b/rxbinding-design-chip/src/main/java/com/jakewharton/rxbinding2/support/design/chip/ChipGroupCheckedChangeObservable.java @@ -0,0 +1,58 @@ +package com.jakewharton.rxbinding2.support.design.chip; + +import android.support.design.chip.ChipGroup; +import android.support.design.chip.ChipGroup.OnCheckedChangeListener; +import android.view.View; + +import com.jakewharton.rxbinding2.InitialValueObservable; +import io.reactivex.Observer; +import io.reactivex.android.MainThreadDisposable; + +import static com.jakewharton.rxbinding2.internal.Preconditions.checkMainThread; + +final class ChipGroupCheckedChangeObservable extends InitialValueObservable { + private final ChipGroup view; + + ChipGroupCheckedChangeObservable(ChipGroup view) { + this.view = view; + } + + @Override + protected void subscribeListener(Observer observer) { + if (!checkMainThread(observer)) { + return; + } + Listener listener = new Listener(view, observer); + view.setOnCheckedChangeListener(listener); + observer.onSubscribe(listener); + } + + @Override + protected Integer getInitialValue() { + return view.getCheckedChipId(); + } + + static final class Listener extends MainThreadDisposable implements OnCheckedChangeListener { + private final ChipGroup view; + private final Observer observer; + private int lastChecked = View.NO_ID; + + Listener(ChipGroup view, Observer observer) { + this.view = view; + this.observer = observer; + } + + @Override + public void onCheckedChanged(ChipGroup chipGroup, int checkedId) { + if (!isDisposed() && checkedId != lastChecked) { + lastChecked = checkedId; + observer.onNext(checkedId); + } + } + + @Override + protected void onDispose() { + view.setOnCheckedChangeListener(null); + } + } +} diff --git a/rxbinding-design-chip/src/main/java/com/jakewharton/rxbinding2/support/design/chip/RxChipGroup.java b/rxbinding-design-chip/src/main/java/com/jakewharton/rxbinding2/support/design/chip/RxChipGroup.java new file mode 100644 index 00000000..93c64a40 --- /dev/null +++ b/rxbinding-design-chip/src/main/java/com/jakewharton/rxbinding2/support/design/chip/RxChipGroup.java @@ -0,0 +1,55 @@ +package com.jakewharton.rxbinding2.support.design.chip; + +import android.support.annotation.CheckResult; +import android.support.annotation.NonNull; +import android.support.design.chip.ChipGroup; +import android.view.View; +import com.jakewharton.rxbinding2.InitialValueObservable; +import io.reactivex.functions.Consumer; + +import static com.jakewharton.rxbinding2.internal.Preconditions.checkNotNull; + +public final class RxChipGroup { + /** + * Create an observable of the checked chip ID changes in {@code view}. + *

+ * Warning: The created observable keeps a strong reference to {@code view}. Unsubscribe + * to free this reference. + *

+ *

+ * Note: A value will be emitted immediately on subscribe + *

+ */ + @CheckResult @NonNull + public static InitialValueObservable checkedChanges(@NonNull ChipGroup view) { + checkNotNull(view, "view == null"); + return new ChipGroupCheckedChangeObservable(view); + } + + /** + * An action which sets the checked child of {@code view} with ID. Passing {@code View.NO_ID} will clear + * any checked view. + *

+ * Warning: The created observable keeps a strong reference to {@code view}. Unsubscribe + * to free this reference + *

+ */ + @CheckResult @NonNull + public static Consumer checked(@NonNull final ChipGroup view) { + checkNotNull(view, "view == null"); + return new Consumer() { + @Override + public void accept(Integer value) { + if (value == View.NO_ID) { + view.clearCheck(); + } else { + view.check(value); + } + } + }; + } + + private RxChipGroup() { + throw new AssertionError("No instances."); + } +} diff --git a/settings.gradle b/settings.gradle index 093a3373..28c14738 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,6 +8,7 @@ include ':rxbinding-appcompat-v7-kotlin' include ':rxbinding-design' include ':rxbinding-design-kotlin' +include ':rxbinding-design-chip' include ':rxbinding-support-v4' include ':rxbinding-support-v4-kotlin'