[SuwLib] Remove button from parent after createButton

Since the button for a ButtonItem is reused, it may be moved to a
different view parent after re-binding. In order to make sure the move
is successful, the button must be first removed from the current parent
before returning.

Bug: 28317915
Change-Id: Ice2a7d1a5f33870775dfd26c1bff816de70526e9
diff --git a/library/main/src/com/android/setupwizardlib/items/ButtonItem.java b/library/main/src/com/android/setupwizardlib/items/ButtonItem.java
index 4faeff4..2ec6489 100644
--- a/library/main/src/com/android/setupwizardlib/items/ButtonItem.java
+++ b/library/main/src/com/android/setupwizardlib/items/ButtonItem.java
@@ -114,6 +114,13 @@
         throw new UnsupportedOperationException("Cannot bind to ButtonItem's view");
     }
 
+    /**
+     * Create a button according to this button item.
+     *
+     * @param parent The parent of the button, used to retrieve the theme and context for this
+     *               button.
+     * @return A button that can be added to the parent.
+     */
     protected Button createButton(ViewGroup parent) {
         if (mButton == null) {
             Context context = parent.getContext();
@@ -122,6 +129,12 @@
             }
             mButton = new Button(context);
             mButton.setOnClickListener(this);
+        } else {
+            if (mButton.getParent() instanceof ViewGroup) {
+                // A view cannot be added to a different parent if one already exists. Remove this
+                // button from its parent before returning.
+                ((ViewGroup) mButton.getParent()).removeView(mButton);
+            }
         }
         mButton.setEnabled(mEnabled);
         mButton.setText(mText);
diff --git a/library/test/src/com/android/setupwizardlib/test/ButtonItemTest.java b/library/test/src/com/android/setupwizardlib/test/ButtonItemTest.java
index 45342d0..3490d4d 100644
--- a/library/test/src/com/android/setupwizardlib/test/ButtonItemTest.java
+++ b/library/test/src/com/android/setupwizardlib/test/ButtonItemTest.java
@@ -21,6 +21,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
+import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 
 import com.android.setupwizardlib.R;
@@ -66,6 +67,18 @@
         assertTrue("Default button text should be empty", TextUtils.isEmpty(button.getText()));
     }
 
+    public void testCreateButtonTwice() {
+        TestButtonItem item = new TestButtonItem();
+        final Button button = item.createButton(mParent);
+
+        FrameLayout frameLayout = new FrameLayout(getContext());
+        frameLayout.addView(button);
+
+        final Button button2 = item.createButton(mParent);
+        assertSame("createButton should be reused", button, button2);
+        assertNull("Should be removed from parent after createButton", button2.getParent());
+    }
+
     public void testSetEnabledTrue() {
         TestButtonItem item = new TestButtonItem();
         item.setEnabled(true);