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