1 package org.robolectric.shadows; 2 3 import static org.robolectric.shadow.api.Shadow.directlyOn; 4 5 import android.os.Looper; 6 import android.view.MotionEvent; 7 import android.view.View; 8 import android.view.ViewGroup; 9 import android.view.animation.Animation.AnimationListener; 10 import android.view.animation.LayoutAnimationController; 11 import java.io.PrintStream; 12 import org.robolectric.Shadows; 13 import org.robolectric.annotation.Implementation; 14 import org.robolectric.annotation.Implements; 15 import org.robolectric.annotation.RealObject; 16 import org.robolectric.util.ReflectionHelpers.ClassParameter; 17 18 @SuppressWarnings({"UnusedDeclaration"}) 19 @Implements(ViewGroup.class) 20 public class ShadowViewGroup extends ShadowView { 21 @RealObject protected ViewGroup realViewGroup; 22 23 private AnimationListener animListener; 24 private LayoutAnimationController layoutAnim; 25 private boolean disallowInterceptTouchEvent = false; 26 private MotionEvent interceptedTouchEvent; 27 28 @Implementation 29 public void addView(final View child, final int index, final ViewGroup.LayoutParams params) { 30 Shadows.shadowOf(Looper.getMainLooper()).runPaused(new Runnable() { 31 @Override public void run() { 32 directlyOn(realViewGroup, ViewGroup.class, "addView", 33 ClassParameter.from(View.class, child), 34 ClassParameter.from(int.class, index), 35 ClassParameter.from(ViewGroup.LayoutParams.class, params)); 36 } 37 }); 38 } 39 40 /** 41 * Returns a string representation of this {@code ViewGroup} by concatenating all of the 42 * strings contained in all of the descendants of this {@code ViewGroup}. 43 */ 44 @Override 45 public String innerText() { 46 String innerText = ""; 47 String delimiter = ""; 48 49 for (int i = 0; i < realViewGroup.getChildCount(); i++) { 50 View child = realViewGroup.getChildAt(i); 51 String childText = Shadows.shadowOf(child).innerText(); 52 if (childText.length() > 0) { 53 innerText += delimiter; 54 delimiter = " "; 55 } 56 innerText += childText; 57 } 58 return innerText; 59 } 60 61 /** 62 * Dumps the state of this {@code ViewGroup} to {@code System.out}. 63 */ 64 @Override 65 public void dump(PrintStream out, int indent) { 66 dumpFirstPart(out, indent); 67 if (realViewGroup.getChildCount() > 0) { 68 out.println(">"); 69 70 for (int i = 0; i < realViewGroup.getChildCount(); i++) { 71 View child = realViewGroup.getChildAt(i); 72 Shadows.shadowOf(child).dump(out, indent + 2); 73 } 74 75 dumpIndent(out, indent); 76 out.println("</" + realView.getClass().getSimpleName() + ">"); 77 } else { 78 out.println("/>"); 79 } 80 } 81 82 @Implementation 83 public void setLayoutAnimationListener(AnimationListener listener) { 84 animListener = listener; 85 } 86 87 @Implementation 88 public AnimationListener getLayoutAnimationListener() { 89 return animListener; 90 } 91 92 @Implementation 93 public void setLayoutAnimation(LayoutAnimationController layoutAnim) { 94 this.layoutAnim = layoutAnim; 95 } 96 97 @Implementation 98 public LayoutAnimationController getLayoutAnimation() { 99 return layoutAnim; 100 } 101 102 @Implementation 103 public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { 104 disallowInterceptTouchEvent = disallowIntercept; 105 } 106 107 public boolean getDisallowInterceptTouchEvent() { 108 return disallowInterceptTouchEvent; 109 } 110 111 protected void removedChild(View child) { 112 if (isAttachedToWindow()) Shadows.shadowOf(child).callOnDetachedFromWindow(); 113 } 114 115 public MotionEvent getInterceptedTouchEvent() { 116 return interceptedTouchEvent; 117 } 118 119 @Implementation 120 public boolean onInterceptTouchEvent(MotionEvent ev) { 121 interceptedTouchEvent = ev; 122 return false; 123 } 124 } 125