diff options
5 files changed, 119 insertions, 57 deletions
diff --git a/compiler/src/main/java/android/databinding/tool/Binding.java b/compiler/src/main/java/android/databinding/tool/Binding.java index 3c2ed67e..530b6b7c 100644 --- a/compiler/src/main/java/android/databinding/tool/Binding.java +++ b/compiler/src/main/java/android/databinding/tool/Binding.java @@ -120,9 +120,7 @@ public class Binding implements LocationScopeProvider { private void resolveSetterCall() { ModelClass viewType = mTarget.getResolvedType(); - if ("android:visibility".equals(mName) && viewType != null && viewType.isViewDataBinding()) { - mSetterCall = new IncludeVisibilityCall(); - } else if (viewType != null && viewType.getExtendsViewStub()) { + if (viewType != null && viewType.getExtendsViewStub()) { mExpr = mExpr.unwrapObservableField(); if (isListenerAttribute(mName)) { ModelAnalyzer modelAnalyzer = ModelAnalyzer.getInstance(); @@ -361,46 +359,4 @@ public class Binding implements LocationScopeProvider { return mWrappedCall.getDescription(); } } - - private static class IncludeVisibilityCall extends SetterCall { - - @Override - public boolean requiresOldValue() { - return false; - } - - @Override - public ModelClass[] getParameterTypes() { - return new ModelClass[] { - ModelAnalyzer.getInstance().loadPrimitive("int") - }; - } - - @Override - public String getBindingAdapterInstanceClass() { - return null; - } - - @Override - public String getDescription() { - return "setVisibility(value)"; - } - - @Override - protected String toJavaInternal(String componentExpression, String viewExpression, - String converted) { - return viewExpression + ".getRoot().setVisibility(" + converted + ")"; - } - - @Override - protected String toJavaInternal(String componentExpression, String viewExpression, - String oldValue, String converted) { - return null; - } - - @Override - public int getMinApi() { - return 0; - } - } } diff --git a/compiler/src/main/java/android/databinding/tool/store/SetterStore.java b/compiler/src/main/java/android/databinding/tool/store/SetterStore.java index c04d73db..12a397c0 100644 --- a/compiler/src/main/java/android/databinding/tool/store/SetterStore.java +++ b/compiler/src/main/java/android/databinding/tool/store/SetterStore.java @@ -25,10 +25,19 @@ import android.databinding.tool.util.GenerationalClassUtil; import android.databinding.tool.util.L; import android.databinding.tool.util.Preconditions; import android.databinding.tool.util.StringUtils; - import com.android.annotations.NonNull; import com.android.annotations.Nullable; +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Types; import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; @@ -45,17 +54,6 @@ import java.util.Set; import java.util.TreeMap; import java.util.stream.Collectors; -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.ArrayType; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.Types; - public class SetterStore { private static final int ASSIGNABLE_CONVERSION = 1; private final BindingAdapterStore mStore; @@ -625,6 +623,18 @@ public class SetterStore { bestSetter.setterCall.setConverter(conversionMethod); } + if (bestSetter.setterCall == null && viewType.isViewDataBinding()) { + // if it is a binding, try to find setter on the view class. + SetterCall rootViewSetter = getSetterCall( + attribute, + viewType.findInstanceGetter("getRoot").getReturnType(), + valueType, + imports); + if (rootViewSetter != null) { + // replace with a root view getter and return it + return new ViewBindingRootViewSetterCall(rootViewSetter); + } + } return bestSetter.setterCall; } @@ -2091,4 +2101,56 @@ public class SetterStore { this.viewType = viewType; } } + + /** + * A ViewBinding can support setters on its root view. This wrapper is injected when include tag + * has a binding on directly its view. + */ + private static class ViewBindingRootViewSetterCall extends SetterCall { + + private final SetterCall mWrapped; + + public ViewBindingRootViewSetterCall(SetterCall wrapped) { + mWrapped = wrapped; + } + + @Override + public boolean requiresOldValue() { + return mWrapped.requiresOldValue(); + } + + @Override + public ModelClass[] getParameterTypes() { + return mWrapped.getParameterTypes(); + } + + @Override + public String getBindingAdapterInstanceClass() { + return mWrapped.getBindingAdapterInstanceClass(); + } + + @Override + public String getDescription() { + return mWrapped.getDescription(); + } + + @Override + protected String toJavaInternal(String componentExpression, String viewExpression, + String converted) { + return mWrapped.toJavaInternal(componentExpression, viewExpression + ".getRoot()", + converted); + } + + @Override + protected String toJavaInternal(String componentExpression, String viewExpression, + String oldValue, String converted) { + return mWrapped.toJavaInternal(componentExpression, viewExpression + ".getRoot()", + oldValue, converted); + } + + @Override + public int getMinApi() { + return mWrapped.getMinApi(); + } + } } diff --git a/integration-tests/TestApp/app/src/androidTest/java/android/databinding/testapp/IncludeTagTest.java b/integration-tests/TestApp/app/src/androidTest/java/android/databinding/testapp/IncludeTagTest.java index 1b5013fa..1d45e23c 100644 --- a/integration-tests/TestApp/app/src/androidTest/java/android/databinding/testapp/IncludeTagTest.java +++ b/integration-tests/TestApp/app/src/androidTest/java/android/databinding/testapp/IncludeTagTest.java @@ -103,6 +103,11 @@ public class IncludeTagTest extends BaseDataBinderTest<LayoutWithIncludeBinding> assertEquals(mBinder.includedPlainLayout.getClass(), FrameLayout.class); assertEquals(((FrameLayout) mBinder.includedPlainLayout).getChildCount(), 0); assertNull(mBinder.includedMergeLayout); + + mBinder.setMinHeight(41); + mBinder.executePendingBindings(); + assertEquals(mBinder.bindingLayoutWithRootViewAdapter.getRoot().getMinimumHeight(), 41); + assertEquals(mBinder.plainLayoutWithBinding.getMinimumHeight(), 41); } // Make sure that when an included layout's executePendingBindings is run that the include diff --git a/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/adapter/IncludeTagAdapter.java b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/adapter/IncludeTagAdapter.java new file mode 100644 index 00000000..be79a409 --- /dev/null +++ b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/adapter/IncludeTagAdapter.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 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 android.databinding.testapp.adapter; + +import android.view.View; +import android.widget.TextView; + +import androidx.databinding.BindingAdapter; + +public class IncludeTagAdapter { + @BindingAdapter("includeMinHeightAdapter") + public static void setMinHeightVia(View view, int minHeight) { + view.setMinimumHeight(minHeight); + } +} diff --git a/integration-tests/TestApp/app/src/main/res/layout/layout_with_include.xml b/integration-tests/TestApp/app/src/main/res/layout/layout_with_include.xml index 1b478586..dfffd996 100644 --- a/integration-tests/TestApp/app/src/main/res/layout/layout_with_include.xml +++ b/integration-tests/TestApp/app/src/main/res/layout/layout_with_include.xml @@ -19,6 +19,7 @@ <variable name="outerObject" type="android.databinding.testapp.vo.NotBindableVo"/> <variable name="map" type="ObservableArrayMap<String, String>"/> <variable name="visibility" type="int"/> + <variable name="minHeight" type="int" /> </data> <FrameLayout android:layout_width="match_parent" @@ -78,6 +79,15 @@ android:id="@+id/trackedInclude" layout="@layout/include_tracker" android:innerObject="@{outerObject}"/> + <include + layout="@layout/simple_text" + android:id="@+id/plainLayoutWithBinding" + bind:includeMinHeightAdapter="@{minHeight}"/> + <include + layout="@layout/included_layout" + android:id="@+id/bindingLayoutWithRootViewAdapter" + bind:includeMinHeightAdapter="@{minHeight}"/> + </LinearLayout> </FrameLayout> </layout> |