1 package org.robolectric.shadows; 2 3 import static org.robolectric.util.reflector.Reflector.reflector; 4 5 import android.content.Context; 6 import android.text.TextWatcher; 7 import android.view.KeyEvent; 8 import android.view.View; 9 import android.widget.TextView; 10 import java.io.PrintStream; 11 import java.util.ArrayList; 12 import java.util.List; 13 import java.util.Locale; 14 import org.robolectric.annotation.HiddenApi; 15 import org.robolectric.annotation.Implementation; 16 import org.robolectric.annotation.Implements; 17 import org.robolectric.annotation.RealObject; 18 import org.robolectric.util.reflector.Direct; 19 import org.robolectric.util.reflector.ForType; 20 21 @SuppressWarnings({"UnusedDeclaration"}) 22 @Implements(TextView.class) 23 public class ShadowTextView extends ShadowView { 24 @RealObject TextView realTextView; 25 26 private TextView.OnEditorActionListener onEditorActionListener; 27 private int textAppearanceId; 28 protected int selectionStart = -1; 29 protected int selectionEnd = -1; 30 31 private List<TextWatcher> watchers = new ArrayList<>(); 32 private List<Integer> previousKeyCodes = new ArrayList<>(); 33 private List<KeyEvent> previousKeyEvents = new ArrayList<>(); 34 private int compoundDrawablesWithIntrinsicBoundsLeft; 35 private int compoundDrawablesWithIntrinsicBoundsTop; 36 private int compoundDrawablesWithIntrinsicBoundsRight; 37 private int compoundDrawablesWithIntrinsicBoundsBottom; 38 39 @Implementation setTextAppearance(Context context, int resid)40 protected void setTextAppearance(Context context, int resid) { 41 textAppearanceId = resid; 42 reflector(TextViewReflector.class, realTextView).setTextAppearance(context, resid); 43 } 44 45 @Implementation onKeyDown(int keyCode, KeyEvent event)46 protected boolean onKeyDown(int keyCode, KeyEvent event) { 47 previousKeyCodes.add(keyCode); 48 previousKeyEvents.add(event); 49 return reflector(TextViewReflector.class, realTextView).onKeyDown(keyCode, event); 50 } 51 52 @Implementation onKeyUp(int keyCode, KeyEvent event)53 protected boolean onKeyUp(int keyCode, KeyEvent event) { 54 previousKeyCodes.add(keyCode); 55 previousKeyEvents.add(event); 56 return reflector(TextViewReflector.class, realTextView).onKeyUp(keyCode, event); 57 } 58 getPreviousKeyCode(int index)59 public int getPreviousKeyCode(int index) { 60 return previousKeyCodes.get(index); 61 } 62 getPreviousKeyEvent(int index)63 public KeyEvent getPreviousKeyEvent(int index) { 64 return previousKeyEvents.get(index); 65 } 66 67 /** 68 * Returns the text string of this {@code TextView}. 69 * 70 * <p>Robolectric extension. 71 */ 72 @Override innerText()73 public String innerText() { 74 CharSequence text = realTextView.getText(); 75 return (text == null || realTextView.getVisibility() != View.VISIBLE) ? "" : text.toString(); 76 } 77 getTextAppearanceId()78 public int getTextAppearanceId() { 79 return textAppearanceId; 80 } 81 82 @Implementation addTextChangedListener(TextWatcher watcher)83 protected void addTextChangedListener(TextWatcher watcher) { 84 this.watchers.add(watcher); 85 reflector(TextViewReflector.class, realTextView).addTextChangedListener(watcher); 86 } 87 88 @Implementation removeTextChangedListener(TextWatcher watcher)89 protected void removeTextChangedListener(TextWatcher watcher) { 90 this.watchers.remove(watcher); 91 reflector(TextViewReflector.class, realTextView).removeTextChangedListener(watcher); 92 } 93 94 /** 95 * @return the list of currently registered watchers/listeners 96 */ getWatchers()97 public List<TextWatcher> getWatchers() { 98 return watchers; 99 } 100 101 @HiddenApi 102 @Implementation getTextServicesLocale()103 public Locale getTextServicesLocale() { 104 return Locale.getDefault(); 105 } 106 107 @Override dumpAttributes(PrintStream out)108 protected void dumpAttributes(PrintStream out) { 109 super.dumpAttributes(out); 110 CharSequence text = realTextView.getText(); 111 if (text != null && text.length() > 0) { 112 dumpAttribute(out, "text", text.toString()); 113 } 114 } 115 116 @Implementation setOnEditorActionListener(TextView.OnEditorActionListener l)117 protected void setOnEditorActionListener(TextView.OnEditorActionListener l) { 118 this.onEditorActionListener = l; 119 reflector(TextViewReflector.class, realTextView).setOnEditorActionListener(l); 120 } 121 getOnEditorActionListener()122 public TextView.OnEditorActionListener getOnEditorActionListener() { 123 return onEditorActionListener; 124 } 125 126 @Implementation setCompoundDrawablesWithIntrinsicBounds(int left, int top, int right, int bottom)127 protected void setCompoundDrawablesWithIntrinsicBounds(int left, int top, int right, int bottom) { 128 this.compoundDrawablesWithIntrinsicBoundsLeft = left; 129 this.compoundDrawablesWithIntrinsicBoundsTop = top; 130 this.compoundDrawablesWithIntrinsicBoundsRight = right; 131 this.compoundDrawablesWithIntrinsicBoundsBottom = bottom; 132 reflector(TextViewReflector.class, realTextView) 133 .setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom); 134 } 135 getCompoundDrawablesWithIntrinsicBoundsLeft()136 public int getCompoundDrawablesWithIntrinsicBoundsLeft() { 137 return compoundDrawablesWithIntrinsicBoundsLeft; 138 } 139 getCompoundDrawablesWithIntrinsicBoundsTop()140 public int getCompoundDrawablesWithIntrinsicBoundsTop() { 141 return compoundDrawablesWithIntrinsicBoundsTop; 142 } 143 getCompoundDrawablesWithIntrinsicBoundsRight()144 public int getCompoundDrawablesWithIntrinsicBoundsRight() { 145 return compoundDrawablesWithIntrinsicBoundsRight; 146 } 147 getCompoundDrawablesWithIntrinsicBoundsBottom()148 public int getCompoundDrawablesWithIntrinsicBoundsBottom() { 149 return compoundDrawablesWithIntrinsicBoundsBottom; 150 } 151 152 @ForType(TextView.class) 153 interface TextViewReflector { 154 155 @Direct setTextAppearance(Context context, int resid)156 void setTextAppearance(Context context, int resid); 157 158 @Direct onKeyDown(int keyCode, KeyEvent event)159 boolean onKeyDown(int keyCode, KeyEvent event); 160 161 @Direct onKeyUp(int keyCode, KeyEvent event)162 boolean onKeyUp(int keyCode, KeyEvent event); 163 164 @Direct addTextChangedListener(TextWatcher watcher)165 void addTextChangedListener(TextWatcher watcher); 166 167 @Direct removeTextChangedListener(TextWatcher watcher)168 void removeTextChangedListener(TextWatcher watcher); 169 170 @Direct setOnEditorActionListener(TextView.OnEditorActionListener l)171 void setOnEditorActionListener(TextView.OnEditorActionListener l); 172 173 @Direct setCompoundDrawablesWithIntrinsicBounds(int left, int top, int right, int bottom)174 void setCompoundDrawablesWithIntrinsicBounds(int left, int top, int right, int bottom); 175 } 176 } 177