summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Mount <mount@google.com>2015-09-17 07:42:41 -0700
committerGeorge Mount <mount@google.com>2016-02-23 15:05:20 -0800
commitb7eeedbfadec03792551014e9dfa2bd384fc21a3 (patch)
tree27a2c93238a1b1f9e83a1b36e47889075aa43cf4
parentb522c7650bf7d9ec566845bc9eb37e761eea853d (diff)
downloaddata-binding-b7eeedbfadec03792551014e9dfa2bd384fc21a3.tar.gz
Two-way binding tests
Bug 1474349 Bug 22460238 Tests for two-way data binding can't be checked in until the SDK becomes public. Also updates the sample application because it has the same restrictions. Change-Id: I7e2b2f84943844401d2b8edbac4e60ea9f5704a6
-rw-r--r--compilationTests/src/test/java/android/databinding/compilationTest/SimpleCompilationTest.java35
-rw-r--r--compilationTests/src/test/resources/layout/layout_with_two_way_event_attribute.xml35
-rw-r--r--integration-tests/TestApp/app/src/androidTestApi14/java/android/databinding/testapp/RootTag.java10
-rw-r--r--integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/BracketTest.java2
-rw-r--r--integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/LeakTest.java4
-rw-r--r--integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/TextViewBindingAdapterTest.java11
-rw-r--r--integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/TwoWayBindingAdapterTest.java718
-rw-r--r--integration-tests/TestApp/app/src/main/java/android/databinding/testapp/adapter/CustomNamespaceAdapter.java2
-rw-r--r--integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/TextViewBindingObject.java12
-rw-r--r--integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/TwoWayBindingObject.java79
-rw-r--r--integration-tests/TestApp/app/src/main/res/layout/bracket_test.xml2
-rw-r--r--integration-tests/TestApp/app/src/main/res/layout/text_view_adapter_test.xml8
-rw-r--r--integration-tests/TestApp/app/src/main/res/layout/two_way.xml175
-rw-r--r--integration-tests/TestApp/app/src/main/res/layout/two_way_included.xml22
-rw-r--r--integration-tests/TestApp/app/src/main/res/layout/view_stub.xml2
-rw-r--r--integration-tests/TestApp/app/src/main/res/values/integers.xml5
-rw-r--r--samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/MainActivity.java8
-rw-r--r--samples/BindingDemo/app/src/main/res/layout/main_activity.xml13
18 files changed, 1101 insertions, 42 deletions
diff --git a/compilationTests/src/test/java/android/databinding/compilationTest/SimpleCompilationTest.java b/compilationTests/src/test/java/android/databinding/compilationTest/SimpleCompilationTest.java
index f38dcc4f..3525b3a8 100644
--- a/compilationTests/src/test/java/android/databinding/compilationTest/SimpleCompilationTest.java
+++ b/compilationTests/src/test/java/android/databinding/compilationTest/SimpleCompilationTest.java
@@ -16,13 +16,6 @@
package android.databinding.compilationTest;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.filefilter.PrefixFileFilter;
-import org.apache.commons.io.filefilter.SuffixFileFilter;
-import org.apache.commons.lang3.StringUtils;
-import org.junit.Test;
-
import android.databinding.tool.processing.ErrorMessages;
import android.databinding.tool.processing.ScopedErrorReport;
import android.databinding.tool.processing.ScopedException;
@@ -30,6 +23,12 @@ import android.databinding.tool.store.Location;
import com.google.common.base.Joiner;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.filefilter.PrefixFileFilter;
+import org.apache.commons.io.filefilter.SuffixFileFilter;
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Test;
+
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
@@ -37,7 +36,6 @@ import java.util.Collection;
import java.util.List;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -327,4 +325,25 @@ public class SimpleCompilationTest extends BaseCompilationTest {
assertEquals("Merge shouldn't support includes as root. Error message was '" + result.error,
ErrorMessages.INCLUDE_INSIDE_MERGE, ex.getBareMessage());
}
+
+ @Test
+ public void testAssignTwoWayEvent() throws Throwable {
+ prepareProject();
+ copyResourceTo("/layout/layout_with_two_way_event_attribute.xml",
+ "/app/src/main/res/layout/layout_with_two_way_event_attribute.xml");
+ CompilationResult result = runGradle("assembleDebug");
+ assertNotEquals(0, result.resultCode);
+ List<ScopedException> errors = ScopedException.extractErrors(result.error);
+ assertEquals(result.error, 1, errors.size());
+ final ScopedException ex = errors.get(0);
+ final ScopedErrorReport report = ex.getScopedErrorReport();
+ final File errorFile = new File(report.getFilePath());
+ assertTrue(errorFile.exists());
+ assertEquals(new File(testFolder,
+ "/app/src/main/res/layout/layout_with_two_way_event_attribute.xml")
+ .getCanonicalFile(),
+ errorFile.getCanonicalFile());
+ assertEquals("The attribute android:textAttrChanged is a two-way binding event attribute " +
+ "and cannot be assigned.", ex.getBareMessage());
+ }
}
diff --git a/compilationTests/src/test/resources/layout/layout_with_two_way_event_attribute.xml b/compilationTests/src/test/resources/layout/layout_with_two_way_event_attribute.xml
new file mode 100644
index 00000000..16536e34
--- /dev/null
+++ b/compilationTests/src/test/resources/layout/layout_with_two_way_event_attribute.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+>
+ <data>
+ <variable name="myVariable" type="String"/>
+ <variable name="myEventListener" type="android.databinding.InverseBindingListener"/>
+ </data>
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <!-- undefined variable -->
+ <TextView android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/textView"
+ android:text="@{myVariable}"
+ android:textAttrChanged="@{myEventListener}"/>
+ </LinearLayout>
+</layout> \ No newline at end of file
diff --git a/integration-tests/TestApp/app/src/androidTestApi14/java/android/databinding/testapp/RootTag.java b/integration-tests/TestApp/app/src/androidTestApi14/java/android/databinding/testapp/RootTag.java
index 132beb6e..9adc8f30 100644
--- a/integration-tests/TestApp/app/src/androidTestApi14/java/android/databinding/testapp/RootTag.java
+++ b/integration-tests/TestApp/app/src/androidTestApi14/java/android/databinding/testapp/RootTag.java
@@ -15,21 +15,17 @@
*/
package android.databinding.testapp;
-import android.databinding.testapp.BaseDataBinderTest;
import android.databinding.testapp.databinding.RootTagBinding;
+import android.test.UiThreadTest;
public class RootTag extends BaseDataBinderTest<RootTagBinding> {
public RootTag() {
super(RootTagBinding.class);
}
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- initBinder();
- }
-
+ @UiThreadTest
public void testRootTagSet() throws Throwable {
+ initBinder();
mBinder.executePendingBindings();
assertEquals("foo", mBinder.textView1.getTag());
assertEquals("hello world", mBinder.textView1.getText().toString());
diff --git a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/BracketTest.java b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/BracketTest.java
index 136b7ccb..a4cda6a2 100644
--- a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/BracketTest.java
+++ b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/BracketTest.java
@@ -94,7 +94,7 @@ public class BracketTest extends BaseDataBinderTest<BracketTestBinding> {
@UiThreadTest
public void testBracketObj() {
mBinder.executePendingBindings();
- assertEquals("Hello World", mBinder.indexObj.getText().toString());
+ assertEquals("Hello World", mBinder.indexObjView.getText().toString());
assertEquals("Hello", mBinder.sparseArrayTextObj.getText().toString());
}
diff --git a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/LeakTest.java b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/LeakTest.java
index 8f63bcc8..5d00b669 100644
--- a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/LeakTest.java
+++ b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/LeakTest.java
@@ -19,6 +19,7 @@ import android.util.Log;
import android.widget.FrameLayout;
import java.lang.ref.WeakReference;
+import java.util.ArrayList;
public class LeakTest extends ActivityInstrumentationTestCase2<TestActivity> {
WeakReference<LeakTestBinding> mWeakReference = new WeakReference<LeakTestBinding>(null);
@@ -63,8 +64,9 @@ public class LeakTest extends ActivityInstrumentationTestCase2<TestActivity> {
}
});
WeakReference<Object> canary = new WeakReference<Object>(new Object());
+ ArrayList<WeakReference<byte[]>> leak = new ArrayList<>();
while (canary.get() != null) {
- byte[] b = new byte[1024 * 1024];
+ leak.add(new WeakReference<byte[]>(new byte[100]));
System.gc();
}
assertNull(mWeakReference.get());
diff --git a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/TextViewBindingAdapterTest.java b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/TextViewBindingAdapterTest.java
index c6bc6715..83dfe728 100644
--- a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/TextViewBindingAdapterTest.java
+++ b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/TextViewBindingAdapterTest.java
@@ -31,6 +31,7 @@ import android.text.method.DialerKeyListener;
import android.text.method.DigitsKeyListener;
import android.text.method.KeyListener;
import android.text.method.TextKeyListener;
+import android.widget.EditText;
import android.widget.TextView;
public class TextViewBindingAdapterTest
@@ -315,4 +316,14 @@ public class TextViewBindingAdapterTest
android.R.color.holo_blue_bright);
assertEquals(expectedColor, textView.getCurrentTextColor());
}
+
+ @UiThreadTest
+ public void testTwoWayText() throws Throwable {
+ EditText view = mBinder.twoWayText;
+ mBindingObject.setText("Hello");
+ mBinder.executePendingBindings();
+ assertEquals("Hello", view.getText().toString());
+ view.setText("World");
+ assertEquals("World", mBindingObject.getText());
+ }
}
diff --git a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/TwoWayBindingAdapterTest.java b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/TwoWayBindingAdapterTest.java
new file mode 100644
index 00000000..7506f2b5
--- /dev/null
+++ b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/TwoWayBindingAdapterTest.java
@@ -0,0 +1,718 @@
+/*
+ * Copyright (C) 2015 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;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.databinding.testapp.databinding.TwoWayBinding;
+import android.databinding.testapp.vo.TwoWayBindingObject;
+import android.os.SystemClock;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.style.BackgroundColorSpan;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.widget.EditText;
+import android.widget.TabHost.TabSpec;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class TwoWayBindingAdapterTest extends BaseDataBinderTest<TwoWayBinding> {
+
+ TwoWayBindingObject mBindingObject;
+
+ public TwoWayBindingAdapterTest() {
+ super(TwoWayBinding.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ initBinder(new Runnable() {
+ @Override
+ public void run() {
+ Context context = getBinder().getRoot().getContext();
+ mBindingObject = new TwoWayBindingObject(context);
+ getBinder().setObj(mBindingObject);
+ getBinder().executePendingBindings();
+ }
+ });
+ }
+
+ public void testListViewSelectedItemPosition() throws Throwable {
+ makeVisible(mBinder.listView);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(0, mBindingObject.selectedItemPosition.get());
+ assertEquals(0, mBinder.listView.getSelectedItemPosition());
+ mBinder.listView.setSelection(1);
+ }
+ });
+ long timeout = SystemClock.uptimeMillis() + 500;
+ while (mBindingObject.selectedItemPosition.get() == 0 &&
+ SystemClock.uptimeMillis() < timeout) {
+ Thread.sleep(1);
+ }
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(1, mBinder.listView.getSelectedItemPosition());
+ assertEquals(1, mBindingObject.selectedItemPosition.get());
+ }
+ });
+ }
+
+ private void clickView(final View view, float offsetX) throws Throwable {
+ final int[] xy = new int[2];
+ final int[] viewSize = new int[2];
+ do {
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ view.getLocationOnScreen(xy);
+ viewSize[0] = view.getWidth();
+ viewSize[1] = view.getHeight();
+ }
+ });
+ } while (xy[0] < 0 || xy[1] < 0);
+
+ final float x = xy[0] + offsetX;
+ final float y = xy[1] + (viewSize[1] / 2f);
+
+ Instrumentation inst = getInstrumentation();
+
+ long downTime = SystemClock.uptimeMillis();
+ long eventTime = SystemClock.uptimeMillis();
+
+ MotionEvent event = MotionEvent.obtain(downTime, eventTime,
+ MotionEvent.ACTION_DOWN, x, y, 0);
+ inst.sendPointerSync(event);
+ inst.waitForIdleSync();
+
+ eventTime = SystemClock.uptimeMillis();
+ final int touchSlop = ViewConfiguration.get(view.getContext()).getScaledTouchSlop();
+ event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE,
+ x + (touchSlop / 2.0f), y + (touchSlop / 2.0f), 0);
+ inst.sendPointerSync(event);
+ inst.waitForIdleSync();
+
+ eventTime = SystemClock.uptimeMillis();
+ event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
+ inst.sendPointerSync(event);
+ inst.waitForIdleSync();
+ }
+
+ private void clickChild(View view, float offsetX) throws Throwable {
+ View childView = view;
+ while (childView != null) {
+ childView.callOnClick();
+ if (childView instanceof ViewGroup) {
+ final ViewGroup viewGroup = (ViewGroup) childView;
+ if (viewGroup.getChildCount() > 0) {
+ childView = viewGroup.getChildAt(0);
+ } else {
+ childView = null;
+ }
+ } else {
+ clickView(childView, offsetX);
+ childView = null;
+ }
+ }
+ }
+
+ public void testCalendarViewDate() throws Throwable {
+ makeVisible(mBinder.calendarView);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertNotSame(0, mBindingObject.date.get());
+ assertEquals(mBindingObject.date.get(), mBinder.calendarView.getDate());
+ }
+ });
+ final long[] date = new long[2];
+ float offsetX = 0;
+ long timeout = SystemClock.uptimeMillis() + 1500;
+ do {
+ // Just randomly poke at the CalendarView to set the date
+ clickChild(mBinder.calendarView, offsetX);
+ offsetX += 48;
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ date[0] = mBinder.calendarView.getDate();
+ if (date[1] == 0) {
+ date[1] = date[0];
+ }
+ }
+ });
+ } while (date[0] == date[1] && SystemClock.uptimeMillis() < timeout);
+
+ timeout = SystemClock.uptimeMillis() + 100;
+ while (mBindingObject.date.get() == 0 && SystemClock.uptimeMillis() < timeout) {
+ Thread.sleep(1);
+ }
+
+ assertEquals(date[0], mBindingObject.date.get());
+ }
+
+ public void testCheckBoxChecked() throws Throwable {
+ makeVisible(mBinder.checkBox);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertFalse(mBindingObject.checked.get());
+ assertFalse(mBinder.checkBox.isChecked());
+ mBinder.checkBox.setChecked(true);
+ }
+ });
+
+ final long timeout = SystemClock.uptimeMillis() + 500;
+ while (!mBindingObject.checked.get() && SystemClock.uptimeMillis() < timeout) {
+ Thread.sleep(1);
+ }
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertTrue(mBinder.checkBox.isChecked());
+ assertTrue(mBindingObject.checked.get());
+ }
+ });
+ }
+
+ private boolean focusOn(final View view) throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ view.requestFocus();
+ }
+ });
+ long timeout = SystemClock.uptimeMillis() + 500;
+ final boolean[] focused = new boolean[1];
+ while (SystemClock.uptimeMillis() < timeout) {
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ focused[0] = view.isFocused();
+ }
+ });
+ if (focused[0]) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void testNumberPickerNumber() throws Throwable {
+ makeVisible(mBinder.textView, mBinder.numberPicker);
+ assertTrue(focusOn(mBinder.textView));
+ final EditText[] pickerText = new EditText[1];
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(1, mBindingObject.number.get());
+ assertEquals(1, mBinder.numberPicker.getValue());
+ for (int i = 0; i < mBinder.numberPicker.getChildCount(); i++) {
+ View view = mBinder.numberPicker.getChildAt(i);
+ if (view instanceof EditText) {
+ pickerText[0] = (EditText) view;
+ break;
+ }
+ }
+ }
+ });
+ assertNotNull(pickerText[0]);
+ assertTrue(focusOn(pickerText[0]));
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ pickerText[0].setText("10");
+ }
+ });
+ assertTrue(focusOn(mBinder.textView));
+
+ final long timeout = SystemClock.uptimeMillis() + 10;
+ while (mBindingObject.number.get() == 1 && SystemClock.uptimeMillis() < timeout) {
+ Thread.sleep(1);
+ }
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(10, mBinder.numberPicker.getValue());
+ assertEquals(10, mBindingObject.number.get());
+ }
+ });
+ }
+
+ public void testRatingBarRating() throws Throwable {
+ makeVisible(mBinder.ratingBar);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(1f, mBindingObject.rating.get());
+ assertEquals(1f, mBinder.ratingBar.getRating());
+ mBinder.ratingBar.setRating(2.5f);
+ }
+ });
+
+ final long timeout = SystemClock.uptimeMillis() + 500;
+ while (mBindingObject.rating.get() == 1f && SystemClock.uptimeMillis() < timeout) {
+ Thread.sleep(1);
+ }
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(2.5f, mBinder.ratingBar.getRating());
+ assertEquals(2.5f, mBindingObject.rating.get());
+ }
+ });
+ }
+
+ public void testSeekBarProgress() throws Throwable {
+ makeVisible(mBinder.seekBar);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(1, mBindingObject.progress.get());
+ assertEquals(1, mBinder.seekBar.getProgress());
+ mBinder.seekBar.setProgress(30);
+ }
+ });
+
+ final long timeout = SystemClock.uptimeMillis() + 500;
+ while (mBindingObject.progress.get() == 1 && SystemClock.uptimeMillis() < timeout) {
+ Thread.sleep(1);
+ }
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(30, mBinder.seekBar.getProgress());
+ assertEquals(30, mBindingObject.progress.get());
+ }
+ });
+ }
+
+ public void testTabHostCurrentTab() throws Throwable {
+ makeVisible(mBinder.tabhost);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mBinder.tabhost.setup();
+ TabSpec tab1 = mBinder.tabhost.newTabSpec("Tab1");
+ TabSpec tab2 = mBinder.tabhost.newTabSpec("Tab2");
+
+ tab1.setIndicator("tab1");
+ tab1.setContent(R.id.foo);
+ tab2.setIndicator("tab2");
+ tab2.setContent(R.id.bar);
+ mBinder.tabhost.addTab(tab1);
+ mBinder.tabhost.addTab(tab2);
+ mBinder.tabhost.setCurrentTab(1);
+ }
+ });
+
+ final long timeout = SystemClock.uptimeMillis() + 500;
+ while (mBindingObject.currentTab.get() == 0 && SystemClock.uptimeMillis() < timeout) {
+ Thread.sleep(1);
+ }
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(1, mBinder.tabhost.getCurrentTab());
+ assertEquals(1, mBindingObject.currentTab.get());
+ }
+ });
+ }
+
+ public void testTextViewText() throws Throwable {
+ makeVisible(mBinder.textView);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(null, mBindingObject.text.get());
+ assertEquals("", mBinder.textView.getText().toString());
+ mBinder.textView.setText("Hello World");
+ }
+ });
+
+ final long timeout = SystemClock.uptimeMillis() + 500;
+ while (mBindingObject.text.get().isEmpty() && SystemClock.uptimeMillis() < timeout) {
+ Thread.sleep(1);
+ }
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals("Hello World", mBinder.textView.getText().toString());
+ assertEquals("Hello World", mBindingObject.text.get());
+ }
+ });
+ }
+
+ public void testDatePicker() throws Throwable {
+ makeVisible(mBinder.datePicker);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(1972, mBindingObject.year.get());
+ assertEquals(9, mBindingObject.month.get());
+ assertEquals(21, mBindingObject.day.get());
+ assertEquals(1972, mBinder.datePicker.getYear());
+ assertEquals(9, mBinder.datePicker.getMonth());
+ assertEquals(21, mBinder.datePicker.getDayOfMonth());
+ mBinder.datePicker.updateDate(2003, 4, 17);
+ }
+ });
+
+ final long timeout = SystemClock.uptimeMillis() + 500;
+ while (mBindingObject.year.get() == 1972 && SystemClock.uptimeMillis() < timeout) {
+ Thread.sleep(1);
+ }
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(2003, mBindingObject.year.get());
+ assertEquals(4, mBindingObject.month.get());
+ assertEquals(17, mBindingObject.day.get());
+ }
+ });
+ }
+
+ public void testExpressions1() throws Throwable {
+ makeVisible(mBinder.expressions1);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(1972, mBindingObject.year.get());
+ assertEquals(9, mBindingObject.month.get());
+ assertEquals(21, mBindingObject.day.get());
+ assertEquals(1972000, mBinder.expressions1.getYear());
+ assertEquals(2, mBinder.expressions1.getMonth());
+ assertEquals(22, mBinder.expressions1.getDayOfMonth());
+ mBinder.expressions1.updateDate(2003000, 3, 18);
+ }
+ });
+
+ final long timeout = SystemClock.uptimeMillis() + 500;
+ while (mBindingObject.year.get() == 1972 && SystemClock.uptimeMillis() < timeout) {
+ Thread.sleep(1);
+ }
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(2003, mBindingObject.year.get());
+ assertEquals(8, mBindingObject.month.get());
+ assertEquals(17, mBindingObject.day.get());
+ }
+ });
+ }
+
+ public void testExpressions2() throws Throwable {
+ makeVisible(mBinder.expressions2);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(1972, mBindingObject.year.get());
+ assertEquals(9, mBindingObject.month.get());
+ assertEquals(21, mBindingObject.day.get());
+ assertEquals(1, mBinder.expressions2.getYear());
+ assertEquals(9, mBinder.expressions2.getMonth());
+ assertEquals(21, mBinder.expressions2.getDayOfMonth());
+ mBinder.expressions2.updateDate(2, 4, 17);
+ }
+ });
+
+ final long timeout = SystemClock.uptimeMillis() + 500;
+ while (mBindingObject.year.get() == 1972 && SystemClock.uptimeMillis() < timeout) {
+ Thread.sleep(1);
+ }
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(2000, mBindingObject.year.get());
+ assertEquals(4, mBindingObject.month.get());
+ assertEquals(17, mBindingObject.day.get());
+ }
+ });
+ }
+
+ public void testExpressions3() throws Throwable {
+ makeVisible(mBinder.expressions3);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals((Integer)1, mBindingObject.list.get(1));
+ assertEquals((Integer)2, mBindingObject.map.get("two"));
+ assertEquals(2, mBindingObject.array.get()[1]);
+ assertEquals(1, mBinder.expressions3.getYear());
+ assertEquals(2, mBinder.expressions3.getMonth());
+ assertEquals(2, mBinder.expressions3.getDayOfMonth());
+ mBinder.expressions3.updateDate(2003, 4, 17);
+ }
+ });
+
+ final long timeout = SystemClock.uptimeMillis() + 500;
+ while (mBindingObject.year.get() == 1972 && SystemClock.uptimeMillis() < timeout) {
+ Thread.sleep(1);
+ }
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals((Integer)2003, mBindingObject.list.get(1));
+ assertEquals((Integer)4, mBindingObject.map.get("two"));
+ assertEquals(17, mBindingObject.array.get()[1]);
+ }
+ });
+ }
+
+ public void testExpressions4() throws Throwable {
+ makeVisible(mBinder.expressions4);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(1972, mBindingObject.year.get());
+ assertEquals(9, mBindingObject.month.get());
+ assertEquals(21, mBindingObject.day.get());
+ assertEquals(50, mBinder.expressions4.getYear());
+ assertEquals(5, mBinder.expressions4.getMonth());
+ assertEquals(21, mBinder.expressions4.getDayOfMonth());
+ mBinder.expressions4.updateDate(49, 4, 17);
+ }
+ });
+
+ final long timeout = SystemClock.uptimeMillis() + 500;
+ while (mBindingObject.year.get() == 1972 && SystemClock.uptimeMillis() < timeout) {
+ Thread.sleep(1);
+ }
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(2040, mBindingObject.year.get());
+ assertEquals(6, mBindingObject.month.get());
+ assertEquals(17, mBindingObject.day.get());
+ }
+ });
+ }
+
+ public void testChaining() throws Throwable {
+ makeVisible(mBinder.checkBox, mBinder.checkBox2);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertTrue(mBinder.checkBox2.isChecked());
+ mBindingObject.checked.set(true);
+ mBinder.executePendingBindings();
+ assertFalse(mBinder.checkBox2.isChecked());
+ }
+ });
+ }
+
+ public void testTwoWayChaining() throws Throwable {
+ makeVisible(mBinder.checkBox3, mBinder.checkBox4);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertFalse(mBinder.checkBox3.isChecked());
+ assertTrue(mBinder.checkBox4.isChecked());
+ mBinder.checkBox3.setChecked(true);
+ mBinder.executePendingBindings();
+ assertTrue(mBinder.checkBox3.isChecked());
+ assertFalse(mBinder.checkBox4.isChecked());
+ }
+ });
+ }
+
+ public void testIncludedTwoWay1() throws Throwable {
+ makeVisible(mBinder.included.editText1, mBinder.textView);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(null, mBindingObject.text.get());
+ assertEquals("", mBinder.textView.getText().toString());
+ assertEquals("", mBinder.included.editText1.getText().toString());
+ mBinder.included.editText1.setText("Hello World");
+ }
+ });
+
+ final long timeout = SystemClock.uptimeMillis() + 500;
+ while (mBindingObject.text.get().isEmpty() && SystemClock.uptimeMillis() < timeout) {
+ Thread.sleep(1);
+ }
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals("Hello World", mBinder.included.editText1.getText().toString());
+ assertEquals("Hello World", mBinder.textView.getText().toString());
+ assertEquals("Hello World", mBindingObject.text.get());
+ }
+ });
+ }
+
+ public void testIncludedTwoWay2() throws Throwable {
+ makeVisible(mBinder.included.editText2, mBinder.textView);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(null, mBindingObject.text.get());
+ assertEquals("", mBinder.textView.getText().toString());
+ assertEquals("", mBinder.included.editText2.getText().toString());
+ mBinder.included.editText2.setText("Hello World");
+ }
+ });
+
+ final long timeout = SystemClock.uptimeMillis() + 500;
+ while (mBindingObject.text.get().isEmpty() && SystemClock.uptimeMillis() < timeout) {
+ Thread.sleep(1);
+ }
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals("Hello World", mBinder.included.editText2.getText().toString());
+ assertEquals("Hello World", mBinder.textView.getText().toString());
+ assertEquals("Hello World", mBindingObject.text.get());
+ }
+ });
+ }
+
+ public void testNoEditableLoop() throws Throwable {
+ makeVisible(mBinder.editText1, mBinder.editText2);
+
+ final SpannableString text = new SpannableString("Hello World Also");
+ BackgroundColorSpan highlight = new BackgroundColorSpan(0xFFFFFF80);
+ text.setSpan(highlight, 0, 5, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+ mBindingObject.textLatch = new CountDownLatch(2);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals("", mBinder.editText1.getText().toString());
+ assertEquals(0, mBindingObject.text1Changes);
+ assertEquals(0, mBindingObject.text2Changes);
+
+ // Change the text of one of the controls
+ mBinder.editText1.setText("Hello World");
+ }
+ });
+
+ assertTrue(mBindingObject.textLatch.await(500, TimeUnit.MILLISECONDS));
+ mBindingObject.textLatch = new CountDownLatch(2);
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertNotNull(mBindingObject.editText.get());
+ assertEquals("Hello World", mBindingObject.editText.get().toString());
+ // They should both be set
+ assertEquals(1, mBindingObject.text1Changes);
+ assertEquals(1, mBindingObject.text2Changes);
+
+ // Edit the span, but the text remains the same.
+ mBinder.editText2.setText(text);
+ }
+ });
+
+ assertTrue(mBindingObject.textLatch.await(500, TimeUnit.MILLISECONDS));
+ mBindingObject.textLatch = new CountDownLatch(1);
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // The one control should notify a change, but not the other.
+ assertEquals(2, mBindingObject.text1Changes);
+ assertEquals(2, mBindingObject.text2Changes);
+
+ // No more changes should occur
+ mBinder.executePendingBindings();
+ }
+ });
+
+ assertFalse(mBindingObject.textLatch.await(200, TimeUnit.MILLISECONDS));
+ mBindingObject.textLatch = new CountDownLatch(2);
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // Nothing changed:
+ assertEquals(2, mBindingObject.text1Changes);
+ assertEquals(2, mBindingObject.text2Changes);
+
+ // Now try changing the value to the same thing. Because the
+ // value is Spannable, it will set it to the EditText
+ // and then get back a String in the onTextChanged.
+ mBindingObject.editText.set(text);
+ }
+ });
+
+ assertTrue(mBindingObject.textLatch.await(500, TimeUnit.MILLISECONDS));
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(3, mBindingObject.text1Changes);
+ assertEquals(3, mBindingObject.text2Changes);
+ assertEquals("Hello World Also", mBindingObject.editText.get());
+ }
+ });
+ }
+
+ private void makeVisible(final View... views) throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mBinder.calendarView.setVisibility(View.GONE);
+ mBinder.listView.setVisibility(View.GONE);
+ mBinder.checkBox.setVisibility(View.GONE);
+ mBinder.numberPicker.setVisibility(View.GONE);
+ mBinder.ratingBar.setVisibility(View.GONE);
+ mBinder.seekBar.setVisibility(View.GONE);
+ mBinder.tabhost.setVisibility(View.GONE);
+ mBinder.textView.setVisibility(View.GONE);
+ mBinder.timePicker.setVisibility(View.GONE);
+ mBinder.datePicker.setVisibility(View.GONE);
+ mBinder.expressions1.setVisibility(View.GONE);
+ mBinder.expressions2.setVisibility(View.GONE);
+ mBinder.expressions3.setVisibility(View.GONE);
+ mBinder.expressions4.setVisibility(View.GONE);
+ mBinder.checkBox2.setVisibility(View.GONE);
+ mBinder.checkBox3.setVisibility(View.GONE);
+ mBinder.checkBox4.setVisibility(View.GONE);
+ mBinder.editText1.setVisibility(View.GONE);
+ mBinder.editText2.setVisibility(View.GONE);
+ mBinder.included.editText1.setVisibility(View.GONE);
+ mBinder.included.editText2.setVisibility(View.GONE);
+ for (View view : views) {
+ view.setVisibility(View.VISIBLE);
+ }
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+ }
+}
diff --git a/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/adapter/CustomNamespaceAdapter.java b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/adapter/CustomNamespaceAdapter.java
index 9b8d8bee..1888bb00 100644
--- a/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/adapter/CustomNamespaceAdapter.java
+++ b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/adapter/CustomNamespaceAdapter.java
@@ -24,7 +24,7 @@ public class CustomNamespaceAdapter {
view.setText(value);
}
- @BindingAdapter({"bind:set2"})
+ @BindingAdapter({"set2"})
public static void setTwo(TextView view, String value) {
view.setText(value);
}
diff --git a/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/TextViewBindingObject.java b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/TextViewBindingObject.java
index b1d04b69..f57638b2 100644
--- a/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/TextViewBindingObject.java
+++ b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/TextViewBindingObject.java
@@ -123,6 +123,9 @@ public class TextViewBindingObject extends BindingAdapterBindingObject {
@Bindable
private float mTextSize = 10f;
+ @Bindable
+ private String mText;
+
public TextView.BufferType getBufferType() {
return mBufferType;
}
@@ -252,6 +255,15 @@ public class TextViewBindingObject extends BindingAdapterBindingObject {
return mTextAllCaps;
}
+ public String getText() {
+ return mText;
+ }
+
+ public void setText(String text) {
+ mText = text;
+ notifyPropertyChanged(BR.text);
+ }
+
public void changeValues() {
mAutoLink = Linkify.EMAIL_ADDRESSES;
mDrawablePadding = 10;
diff --git a/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/TwoWayBindingObject.java b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/TwoWayBindingObject.java
new file mode 100644
index 00000000..873b1dce
--- /dev/null
+++ b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/TwoWayBindingObject.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2015 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.vo;
+
+import android.content.Context;
+import android.databinding.ObservableArrayList;
+import android.databinding.ObservableArrayMap;
+import android.databinding.ObservableBoolean;
+import android.databinding.ObservableField;
+import android.databinding.ObservableFloat;
+import android.databinding.ObservableInt;
+import android.databinding.ObservableLong;
+import android.widget.ArrayAdapter;
+import android.widget.ListAdapter;
+
+import java.util.concurrent.CountDownLatch;
+
+public class TwoWayBindingObject {
+ private static final String[] VALUES = {
+ "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"
+ };
+ public final ListAdapter adapter;
+ public final ObservableInt selectedItemPosition = new ObservableInt();
+ public final ObservableLong date = new ObservableLong(System.currentTimeMillis());
+ public final ObservableBoolean checked = new ObservableBoolean();
+ public final ObservableInt number = new ObservableInt(1);
+ public final ObservableFloat rating = new ObservableFloat(1);
+ public final ObservableInt progress = new ObservableInt(1);
+ public final ObservableInt currentTab = new ObservableInt();
+ public final ObservableField<String> text = new ObservableField<>();
+ public final ObservableInt hour = new ObservableInt();
+ public final ObservableInt minute = new ObservableInt();
+ public final ObservableInt year = new ObservableInt(1972);
+ public final ObservableInt month = new ObservableInt(9);
+ public final ObservableInt day = new ObservableInt(21);
+ public final ObservableArrayList<Integer> list = new ObservableArrayList<>();
+ public final ObservableArrayMap<String, Integer> map = new ObservableArrayMap<>();
+ public final ObservableField<int[]> array = new ObservableField<>();
+ public final ObservableField<CharSequence> editText = new ObservableField<>();
+ public int text1Changes;
+ public int text2Changes;
+ public CountDownLatch textLatch;
+
+ public TwoWayBindingObject(Context context) {
+ this.adapter = new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, VALUES);
+ int[] arr = new int[10];
+ for (int i = 0; i < 10; i++) {
+ list.add(i);
+ arr[i] = i + 1;
+ }
+ array.set(arr);
+ for (int i = 0; i < VALUES.length; i++) {
+ map.put(VALUES[i], i + 1);
+ }
+ }
+
+ public void textChanged1(CharSequence s, int start, int before, int count) {
+ text1Changes++;
+ textLatch.countDown();
+ }
+
+ public void textChanged2(CharSequence s, int start, int before, int count) {
+ text2Changes++;
+ textLatch.countDown();
+ }
+}
diff --git a/integration-tests/TestApp/app/src/main/res/layout/bracket_test.xml b/integration-tests/TestApp/app/src/main/res/layout/bracket_test.xml
index e9a0e2f9..04beb943 100644
--- a/integration-tests/TestApp/app/src/main/res/layout/bracket_test.xml
+++ b/integration-tests/TestApp/app/src/main/res/layout/bracket_test.xml
@@ -35,7 +35,7 @@
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:id="@+id/indexObj"
+ android:id="@+id/indexObjView"
android:text="@{array[indexObj]}"/>
<TextView android:layout_width="wrap_content"
diff --git a/integration-tests/TestApp/app/src/main/res/layout/text_view_adapter_test.xml b/integration-tests/TestApp/app/src/main/res/layout/text_view_adapter_test.xml
index 43b11da0..12aa6ed1 100644
--- a/integration-tests/TestApp/app/src/main/res/layout/text_view_adapter_test.xml
+++ b/integration-tests/TestApp/app/src/main/res/layout/text_view_adapter_test.xml
@@ -87,6 +87,10 @@
<TextView android:layout_width="match_parent" android:layout_height="match_parent"
android:id="@+id/textWithColor"
android:textColor="@{@android:color/holo_blue_bright}"
- />
+ />
+ <EditText android:layout_width="match_parent" android:layout_height="match_parent"
+ android:id="@+id/twoWayText"
+ android:text="@={obj.text}"
+ />
</LinearLayout>
-</layout> \ No newline at end of file
+</layout>
diff --git a/integration-tests/TestApp/app/src/main/res/layout/two_way.xml b/integration-tests/TestApp/app/src/main/res/layout/two_way.xml
new file mode 100644
index 00000000..3ca95888
--- /dev/null
+++ b/integration-tests/TestApp/app/src/main/res/layout/two_way.xml
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<layout xmlns:android="http://schemas.android.com/apk/res/android">
+ <data>
+ <variable name="obj" type="android.databinding.testapp.vo.TwoWayBindingObject"/>
+ </data>
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <CalendarView
+ android:id="@+id/calendarView"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:date="@={obj.date}"
+ />
+ <ListView
+ android:id="@+id/listView"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:selectedItemPosition="@={obj.selectedItemPosition}"
+ android:adapter="@{obj.adapter}"
+ />
+ <CheckBox
+ android:id="@+id/checkBox"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:checked="@={obj.checked}"
+ android:text="Check Box"
+ />
+ <NumberPicker
+ android:id="@+id/numberPicker"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:value="@={obj.number}"
+ android:minValue="@{1}"
+ android:maxValue="@{100}"
+ />
+ <RatingBar
+ android:id="@+id/ratingBar"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:rating="@={obj.rating}"
+ android:numStars="5"
+ />
+ <SeekBar
+ android:id="@+id/seekBar"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:max="100"
+ android:progress="@={obj.progress}"
+ />
+ <TabHost
+ android:id="@android:id/tabhost"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:currentTab="@={obj.currentTab}">
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <TabWidget
+ android:id="@android:id/tabs"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+ <FrameLayout
+ android:id="@android:id/tabcontent"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <View
+ android:id="@+id/foo"
+ android:layout_width="10dp"
+ android:layout_height="10dp"/>
+ <View
+ android:id="@+id/bar"
+ android:layout_width="10dp"
+ android:layout_height="10dp"/>
+ </FrameLayout>
+ </LinearLayout>
+ </TabHost>
+ <EditText
+ android:id="@+id/textView"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@={obj.text}"
+ />
+ <TimePicker
+ android:id="@+id/timePicker"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:hour="@={obj.hour}"
+ android:minute="@={obj.minute}"
+ />
+ <DatePicker
+ android:id="@+id/datePicker"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:year="@={obj.year}"
+ android:month="@={obj.month}"
+ android:day="@={obj.day}"/>
+ <DatePicker
+ android:id="@+id/expressions1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:year="@={obj.year * @integer/oneThousand}"
+ android:month="@={11 - obj.month}"
+ android:day="@={obj.day + 1}"/>
+ <DatePicker
+ android:id="@+id/expressions2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:year="@={obj.year / @integer/oneThousand}"
+ android:month="@={@bool/alwaysTrue ? obj.month : obj.day}"
+ android:day="@={@bool/alwaysFalse ? obj.month : obj.day}"/>
+ <DatePicker
+ android:id="@+id/expressions3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:year="@={obj.list[@integer/one]}"
+ android:month="@={obj.map[`two`]}"
+ android:day="@={obj.array[1]}"/>
+ <DatePicker
+ android:id="@+id/expressions4"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:year="@={(int)(100000f/obj.year)}"
+ android:month="@={1 + (obj.month / 2)}"
+ android:day="@={true ? obj.day : obj.month}"/>
+ <CheckBox
+ android:id="@+id/checkBox2"
+ android:checked="@{!checkBox.checked}"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ <CheckBox
+ android:id="@+id/checkBox3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ <CheckBox
+ android:id="@+id/checkBox4"
+ android:checked="@{!checkBox3.checked}"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ <include
+ android:id="@+id/included"
+ layout="@layout/two_way_included"
+ android:obj="@{obj}"
+ android:text="@={obj.text}"/>
+ <EditText
+ android:id="@+id/editText1"
+ android:text="@={obj.editText}"
+ android:bufferType="editable"
+ android:onTextChanged="@{obj.textChanged1}"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ <EditText
+ android:id="@+id/editText2"
+ android:text="@={obj.editText}"
+ android:bufferType="editable"
+ android:onTextChanged="@{obj.textChanged2}"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ </LinearLayout>
+</layout>
diff --git a/integration-tests/TestApp/app/src/main/res/layout/two_way_included.xml b/integration-tests/TestApp/app/src/main/res/layout/two_way_included.xml
new file mode 100644
index 00000000..a1a02e02
--- /dev/null
+++ b/integration-tests/TestApp/app/src/main/res/layout/two_way_included.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android">
+ <data>
+ <variable name="text" type="String"/>
+ <variable name="obj" type="android.databinding.testapp.vo.TwoWayBindingObject"/>
+ </data>
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <EditText
+ android:id="@+id/editText1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@={text}"/>
+ <EditText
+ android:id="@+id/editText2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@={obj.text}"/>
+ </LinearLayout>
+</layout> \ No newline at end of file
diff --git a/integration-tests/TestApp/app/src/main/res/layout/view_stub.xml b/integration-tests/TestApp/app/src/main/res/layout/view_stub.xml
index 322c9668..b6af0fac 100644
--- a/integration-tests/TestApp/app/src/main/res/layout/view_stub.xml
+++ b/integration-tests/TestApp/app/src/main/res/layout/view_stub.xml
@@ -12,11 +12,9 @@
xmlns:bind="http://schemas.android.com/apk/res-auto">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="@{firstName}"
- android:id="@+id/firstName"
/>
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="@{lastName}"
- android:id="@+id/lastName"
/>
<ViewStub android:layout_width="match_parent" android:layout_height="match_parent"
diff --git a/integration-tests/TestApp/app/src/main/res/values/integers.xml b/integration-tests/TestApp/app/src/main/res/values/integers.xml
new file mode 100644
index 00000000..b56db93c
--- /dev/null
+++ b/integration-tests/TestApp/app/src/main/res/values/integers.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <integer name="oneThousand">1000</integer>
+ <integer name="one">1</integer>
+</resources> \ No newline at end of file
diff --git a/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/MainActivity.java b/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/MainActivity.java
index 68c76c90..bcdcdba1 100644
--- a/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/MainActivity.java
+++ b/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/MainActivity.java
@@ -69,14 +69,6 @@ public class MainActivity extends ActionBarActivity implements Observable {
mListeners.notifyChange(this, BR.selected);
}
- public void onSave(View v) {
- if (selected == null) {
- return;
- }
- selected.setName(dataBinder.selectedName.getText().toString());
- selected.setLastName(dataBinder.selectedLastname.getText().toString());
- }
-
public void onUnselect (View v) {
setSelected(null);
}
diff --git a/samples/BindingDemo/app/src/main/res/layout/main_activity.xml b/samples/BindingDemo/app/src/main/res/layout/main_activity.xml
index c16a94f1..e17f27a6 100644
--- a/samples/BindingDemo/app/src/main/res/layout/main_activity.xml
+++ b/samples/BindingDemo/app/src/main/res/layout/main_activity.xml
@@ -93,7 +93,7 @@ if they are getting complex.-->
android:layout_row="0"
android:background="@android:color/holo_blue_dark"
android:gravity="center"
- android:text="@{activity.selected.name}" />
+ android:text="@={activity.selected.name}" />
<EditText
android:id="@+id/selected_lastname"
@@ -104,16 +104,7 @@ if they are getting complex.-->
android:layout_row="1"
android:background="@android:color/holo_blue_bright"
android:gravity="center"
- android:text="@{activity.selected.lastName}" />
- <Button
- android:id="@+id/edit_button"
- android:onClick="@{activity.onSave}"
- android:text='@{"Save changes to " + activity.selected.name}'
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_column="1"
- android:layout_gravity="right"
- android:layout_row="2"/>
+ android:text="@={activity.selected.lastName}" />
<Button
android:id="@+id/delete_button"