Loading src/com/android/calculator2/CalculatorResult.java +69 −108 Original line number Diff line number Diff line Loading @@ -65,29 +65,24 @@ public class CalculatorResult extends TextView { private boolean mScrollable = false; // A scrollable result is currently displayed. private boolean mValid = false; // The result holds something valid; either a // a number or an error message. private int mCurrentPos;// Position of right of display relative // to decimal point, in pixels. // Large positive values mean the decimal // point is scrolled off the left of the // display. Zero means decimal point is // barely displayed on the right. // The result holds something valid; either a a number or an error // message. private int mCurrentPos;// Position of right of display relative to decimal point, in pixels. // Large positive values mean the decimal point is scrolled off the // left of the display. Zero means decimal point is barely displayed // on the right. private int mLastPos; // Position already reflected in display. private int mMinPos; // Maximum position before all digits // digits disappear of the right. private int mMinPos; // Maximum position before all digits disappear of the right. private Object mWidthLock = new Object(); // Protects the next two fields. private int mWidthConstraint = -1; // Our total width in pixels. private int mCharWidth = 1; // Maximum character width. // For now we pretend that all characters // Maximum character width. For now we pretend that all characters // have this width. // TODO: We're not really using a fixed // width font. But it appears to be close // enough for the characters we use that // the difference is not noticeable. // TODO: We're not really using a fixed width font. But it appears // to be close enough for the characters we use that the difference // is not noticeable. private static final int MAX_WIDTH = 100; // Maximum number of digits displayed private ActionMode mActionMode; Loading @@ -113,9 +108,8 @@ public class CalculatorResult extends TextView { CalculatorResult.this.cancelLongPress(); // Ignore scrolls of error string, etc. if (!mScrollable) return true; mScroller.fling(mCurrentPos, 0, - (int) velocityX, 0 /* horizontal only */, mMinPos, MAX_RIGHT_SCROLL, 0, 0); mScroller.fling(mCurrentPos, 0, - (int) velocityX, 0 /* horizontal only */, mMinPos, MAX_RIGHT_SCROLL, 0, 0); ViewCompat.postInvalidateOnAnimation(CalculatorResult.this); return true; } Loading @@ -132,8 +126,7 @@ public class CalculatorResult extends TextView { if (!mScrollable) return true; int duration = (int)(e2.getEventTime() - e1.getEventTime()); if (duration < 1 || duration > 100) duration = 10; mScroller.startScroll(mCurrentPos, 0, (int)distanceX, 0, (int)duration); mScroller.startScroll(mCurrentPos, 0, (int)distanceX, 0, (int)duration); ViewCompat.postInvalidateOnAnimation(CalculatorResult.this); return true; } Loading Loading @@ -165,24 +158,19 @@ public class CalculatorResult extends TextView { char testChar = KeyMaps.translateResult("5").charAt(0); // TODO: Redo on Locale change? Doesn't seem to matter? // We try to determine the maximal size of a digit plus // corresponding inter-character space. // We assume that "5" has maximal width. Since any // string includes one fewer inter-character space than // characters, me measure one that's longer than any real // display string, and then divide by the number of characters. // This should bound the per-character space we need for any // real string. // We try to determine the maximal size of a digit plus corresponding inter-character // space. We assume that "5" has maximal width. Since any string includes one fewer // inter-character space than characters, me measure one that's longer than any real // display string, and then divide by the number of characters. This should bound // the per-character space we need for any real string. StringBuilder sb = new StringBuilder(MAX_WIDTH); for (int i = 0; i < MAX_WIDTH; ++i) { sb.append(testChar); } final int newWidthConstraint = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight(); MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight(); final int newCharWidth = (int)Math.ceil(getPaint().measureText(sb.toString()) / MAX_WIDTH); (int)Math.ceil(getPaint().measureText(sb.toString()) / MAX_WIDTH); synchronized(mWidthLock) { mWidthConstraint = newWidthConstraint; mCharWidth = newCharWidth; Loading Loading @@ -212,23 +200,20 @@ public class CalculatorResult extends TextView { private final int MAX_COPY_SIZE = 1000000; // Format a result returned by Evaluator.getString() into a single // line containing ellipses (if appropriate) and an exponent // (if appropriate). digs is the value that was passed to // getString and thus identifies the significance of the // rightmost digit. // Format a result returned by Evaluator.getString() into a single line containing ellipses // (if appropriate) and an exponent (if appropriate). digs is the value that was passed to // getString and thus identifies the significance of the rightmost digit. // We add two distinct kinds of exponents: // 1) If the final result contains the leading digit we use standard // scientific notation. // 2) If not, we add an exponent corresponding to an interpretation // of the final result as an integer. // 1) If the final result contains the leading digit we use standard scientific notation. // 2) If not, we add an exponent corresponding to an interpretation of the final result as // an integer. // We add an ellipsis on the left if the result was truncated. // We add ellipses and exponents in a way that leaves most digits // in the position they would have been in had we not done so. // This minimizes jumps as a result of scrolling. // Result is NOT internationalized, uses "e" for exponent. // last_included[0] is set to the position of the last digit we // actually include; thus caller can tell whether result is exact. // We add ellipses and exponents in a way that leaves most digits in the position they // would have been in had we not done so. // This minimizes jumps as a result of scrolling. Result is NOT internationalized, // uses "e" for exponent. // last_included[0] is set to the position of the last digit we actually include; // thus caller can tell whether result is exact. public String formatResult(String res, int digs, int maxDigs, boolean truncated, boolean negative) { Loading @@ -238,21 +223,15 @@ public class CalculatorResult extends TextView { int decIndex = res.indexOf('.'); int resLen = res.length(); if (decIndex == -1 && digs != -1) { // No decimal point displayed, and it's not just // to the right of the last digit. // Add an exponent to let the user track which // digits are currently displayed. // This is a bit tricky, since the number of displayed // digits affects the displayed exponent, which can // affect the room we have for mantissa digits. // We occasionally display one digit too few. // This is sometimes unavoidable, but we could // No decimal point displayed, and it's not just to the right of the last digit. // Add an exponent to let the user track which digits are currently displayed. // This is a bit tricky, since the number of displayed digits affects the displayed // exponent, which can affect the room we have for mantissa digits. We occasionally // display one digit too few. This is sometimes unavoidable, but we could // avoid it in more cases. int exp = digs > 0 ? -digs : -digs - 1; // Can be used as TYPE (2) EXPONENT. // -1 accounts for decimal point. int msd; // Position of most significant digit in res // or indication its outside res. // Can be used as TYPE (2) EXPONENT. -1 accounts for decimal point. int msd; // Position of most significant digit in res or indication its outside res. boolean hasPoint = false; if (truncated) { msd = -1; Loading @@ -261,16 +240,14 @@ public class CalculatorResult extends TextView { } if (msd < maxDigs - 1 && msd >= 0) { // TYPE (1) EXPONENT computation and transformation: // Leading digit is in display window. // Use standard calculator scientific notation // with one digit to the left of the decimal point. // Insert decimal point and delete leading zeroes. // Leading digit is in display window. Use standard calculator scientific notation // with one digit to the left of the decimal point. Insert decimal point and // delete leading zeroes. String fraction = res.substring(msd + 1, resLen); res = (negative ? "-" : "") + res.substring(msd, msd+1) + "." + fraction; res = (negative ? "-" : "") + res.substring(msd, msd+1) + "." + fraction; exp += resLen - msd - 1; // Original exp was correct for decimal point at right // of fraction. Adjust by length of fraction. // Original exp was correct for decimal point at right of fraction. // Adjust by length of fraction. resLen = res.length(); hasPoint = true; } Loading @@ -279,8 +256,7 @@ public class CalculatorResult extends TextView { String expAsString = Integer.toString(exp); int expDigits = expAsString.length(); int dropDigits = expDigits + 1; // Drop digits even if there is room. // Otherwise the scrolling gets jumpy. // Drop digits even if there is room. Otherwise the scrolling gets jumpy. if (dropDigits >= resLen - 1) { dropDigits = Math.max(resLen - 2, 0); // Jumpy is better than no mantissa. Loading @@ -289,11 +265,9 @@ public class CalculatorResult extends TextView { // Special handling for TYPE(2) EXPONENT: exp += dropDigits; expAsString = Integer.toString(exp); // Adjust for digits we are about to drop // to drop to make room for exponent. // This can affect the room we have for the // mantissa. We adjust only for positive exponents, // when it could otherwise result in a truncated // Adjust for digits we are about to drop to drop to make room for exponent. // This can affect the room we have for the mantissa. We adjust only for // positive exponents, when it could otherwise result in a truncated // displayed result. if (exp > 0 && expAsString.length() > expDigits) { // ++expDigits; (dead code) Loading @@ -315,10 +289,8 @@ public class CalculatorResult extends TextView { final boolean truncated[] = new boolean[1]; final boolean negative[] = new boolean[1]; final int requested_prec[] = {pos}; final String raw_res = mEvaluator.getString(requested_prec, maxSize, truncated, negative); return formatResult(raw_res, requested_prec[0], maxSize, truncated[0], negative[0]); final String raw_res = mEvaluator.getString(requested_prec, maxSize, truncated, negative); return formatResult(raw_res, requested_prec[0], maxSize, truncated[0], negative[0]); } // Return entire result (within reason) up to current displayed precision. Loading @@ -326,16 +298,14 @@ public class CalculatorResult extends TextView { if (!mValid) return ""; if (!mScrollable) return getText().toString(); int currentCharPos = getCurrentCharPos(); return KeyMaps.translateResult( getFormattedResult(currentCharPos, MAX_COPY_SIZE)); return KeyMaps.translateResult(getFormattedResult(currentCharPos, MAX_COPY_SIZE)); } public boolean fullTextIsExact() { BoundedRational rat = mEvaluator.getRational(); int currentCharPos = getCurrentCharPos(); if (currentCharPos == -1) { // Suppressing decimal point; still showing all // integral digits. // Suppressing decimal point; still showing all integral digits. currentCharPos = 0; } // TODO: Could handle scientific notation cases better; Loading @@ -345,19 +315,16 @@ public class CalculatorResult extends TextView { // May be called asynchronously from non-UI thread. int getMaxChars() { // We only use 2/3 of the available space, since the // left 1/3 of the result is not visible when it is shown // in large size. // We only use 2/3 of the available space, since the left 1/3 of the result is not // visible when it is shown in large size. int result; synchronized(mWidthLock) { result = 2 * mWidthConstraint / (3 * mCharWidth); // We can apparently finish evaluating before // onMeasure in CalculatorText has been called, in // which case we get 0 or -1 as the width constraint. // We can apparently finish evaluating before onMeasure in CalculatorText has been // called, in which case we get 0 or -1 as the width constraint. } if (result <= 0) { // Return something conservatively big, to force sufficient // evaluation. // Return something conservatively big, to force sufficient evaluation. return MAX_WIDTH; } else { return result; Loading Loading @@ -412,8 +379,7 @@ public class CalculatorResult extends TextView { // Copy support: private ActionMode.Callback mCopyActionModeCallback = new ActionMode.Callback() { private ActionMode.Callback mCopyActionModeCallback = new ActionMode.Callback() { @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { MenuInflater inflater = mode.getMenuInflater(); Loading Loading @@ -461,19 +427,14 @@ public class CalculatorResult extends TextView { private void copyContent() { final CharSequence text = getFullText(); ClipboardManager clipboard = (ClipboardManager) getContext().getSystemService( Context.CLIPBOARD_SERVICE); // We include a tag URI, to allow us to recognize our // own results and handle them specially. ClipData.Item newItem = new ClipData.Item(text, null, mEvaluator.capture()); String[] mimeTypes = new String[] {ClipDescription.MIMETYPE_TEXT_PLAIN}; ClipData cd = new ClipData("calculator result", mimeTypes, newItem); (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE); // We include a tag URI, to allow us to recognize our own results and handle them // specially. ClipData.Item newItem = new ClipData.Item(text, null, mEvaluator.capture()); String[] mimeTypes = new String[] {ClipDescription.MIMETYPE_TEXT_PLAIN}; ClipData cd = new ClipData("calculator result", mimeTypes, newItem); clipboard.setPrimaryClip(cd); Toast.makeText(getContext(), R.string.text_copied_toast, Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(), R.string.text_copied_toast, Toast.LENGTH_SHORT).show(); } } Loading
src/com/android/calculator2/CalculatorResult.java +69 −108 Original line number Diff line number Diff line Loading @@ -65,29 +65,24 @@ public class CalculatorResult extends TextView { private boolean mScrollable = false; // A scrollable result is currently displayed. private boolean mValid = false; // The result holds something valid; either a // a number or an error message. private int mCurrentPos;// Position of right of display relative // to decimal point, in pixels. // Large positive values mean the decimal // point is scrolled off the left of the // display. Zero means decimal point is // barely displayed on the right. // The result holds something valid; either a a number or an error // message. private int mCurrentPos;// Position of right of display relative to decimal point, in pixels. // Large positive values mean the decimal point is scrolled off the // left of the display. Zero means decimal point is barely displayed // on the right. private int mLastPos; // Position already reflected in display. private int mMinPos; // Maximum position before all digits // digits disappear of the right. private int mMinPos; // Maximum position before all digits disappear of the right. private Object mWidthLock = new Object(); // Protects the next two fields. private int mWidthConstraint = -1; // Our total width in pixels. private int mCharWidth = 1; // Maximum character width. // For now we pretend that all characters // Maximum character width. For now we pretend that all characters // have this width. // TODO: We're not really using a fixed // width font. But it appears to be close // enough for the characters we use that // the difference is not noticeable. // TODO: We're not really using a fixed width font. But it appears // to be close enough for the characters we use that the difference // is not noticeable. private static final int MAX_WIDTH = 100; // Maximum number of digits displayed private ActionMode mActionMode; Loading @@ -113,9 +108,8 @@ public class CalculatorResult extends TextView { CalculatorResult.this.cancelLongPress(); // Ignore scrolls of error string, etc. if (!mScrollable) return true; mScroller.fling(mCurrentPos, 0, - (int) velocityX, 0 /* horizontal only */, mMinPos, MAX_RIGHT_SCROLL, 0, 0); mScroller.fling(mCurrentPos, 0, - (int) velocityX, 0 /* horizontal only */, mMinPos, MAX_RIGHT_SCROLL, 0, 0); ViewCompat.postInvalidateOnAnimation(CalculatorResult.this); return true; } Loading @@ -132,8 +126,7 @@ public class CalculatorResult extends TextView { if (!mScrollable) return true; int duration = (int)(e2.getEventTime() - e1.getEventTime()); if (duration < 1 || duration > 100) duration = 10; mScroller.startScroll(mCurrentPos, 0, (int)distanceX, 0, (int)duration); mScroller.startScroll(mCurrentPos, 0, (int)distanceX, 0, (int)duration); ViewCompat.postInvalidateOnAnimation(CalculatorResult.this); return true; } Loading Loading @@ -165,24 +158,19 @@ public class CalculatorResult extends TextView { char testChar = KeyMaps.translateResult("5").charAt(0); // TODO: Redo on Locale change? Doesn't seem to matter? // We try to determine the maximal size of a digit plus // corresponding inter-character space. // We assume that "5" has maximal width. Since any // string includes one fewer inter-character space than // characters, me measure one that's longer than any real // display string, and then divide by the number of characters. // This should bound the per-character space we need for any // real string. // We try to determine the maximal size of a digit plus corresponding inter-character // space. We assume that "5" has maximal width. Since any string includes one fewer // inter-character space than characters, me measure one that's longer than any real // display string, and then divide by the number of characters. This should bound // the per-character space we need for any real string. StringBuilder sb = new StringBuilder(MAX_WIDTH); for (int i = 0; i < MAX_WIDTH; ++i) { sb.append(testChar); } final int newWidthConstraint = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight(); MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight(); final int newCharWidth = (int)Math.ceil(getPaint().measureText(sb.toString()) / MAX_WIDTH); (int)Math.ceil(getPaint().measureText(sb.toString()) / MAX_WIDTH); synchronized(mWidthLock) { mWidthConstraint = newWidthConstraint; mCharWidth = newCharWidth; Loading Loading @@ -212,23 +200,20 @@ public class CalculatorResult extends TextView { private final int MAX_COPY_SIZE = 1000000; // Format a result returned by Evaluator.getString() into a single // line containing ellipses (if appropriate) and an exponent // (if appropriate). digs is the value that was passed to // getString and thus identifies the significance of the // rightmost digit. // Format a result returned by Evaluator.getString() into a single line containing ellipses // (if appropriate) and an exponent (if appropriate). digs is the value that was passed to // getString and thus identifies the significance of the rightmost digit. // We add two distinct kinds of exponents: // 1) If the final result contains the leading digit we use standard // scientific notation. // 2) If not, we add an exponent corresponding to an interpretation // of the final result as an integer. // 1) If the final result contains the leading digit we use standard scientific notation. // 2) If not, we add an exponent corresponding to an interpretation of the final result as // an integer. // We add an ellipsis on the left if the result was truncated. // We add ellipses and exponents in a way that leaves most digits // in the position they would have been in had we not done so. // This minimizes jumps as a result of scrolling. // Result is NOT internationalized, uses "e" for exponent. // last_included[0] is set to the position of the last digit we // actually include; thus caller can tell whether result is exact. // We add ellipses and exponents in a way that leaves most digits in the position they // would have been in had we not done so. // This minimizes jumps as a result of scrolling. Result is NOT internationalized, // uses "e" for exponent. // last_included[0] is set to the position of the last digit we actually include; // thus caller can tell whether result is exact. public String formatResult(String res, int digs, int maxDigs, boolean truncated, boolean negative) { Loading @@ -238,21 +223,15 @@ public class CalculatorResult extends TextView { int decIndex = res.indexOf('.'); int resLen = res.length(); if (decIndex == -1 && digs != -1) { // No decimal point displayed, and it's not just // to the right of the last digit. // Add an exponent to let the user track which // digits are currently displayed. // This is a bit tricky, since the number of displayed // digits affects the displayed exponent, which can // affect the room we have for mantissa digits. // We occasionally display one digit too few. // This is sometimes unavoidable, but we could // No decimal point displayed, and it's not just to the right of the last digit. // Add an exponent to let the user track which digits are currently displayed. // This is a bit tricky, since the number of displayed digits affects the displayed // exponent, which can affect the room we have for mantissa digits. We occasionally // display one digit too few. This is sometimes unavoidable, but we could // avoid it in more cases. int exp = digs > 0 ? -digs : -digs - 1; // Can be used as TYPE (2) EXPONENT. // -1 accounts for decimal point. int msd; // Position of most significant digit in res // or indication its outside res. // Can be used as TYPE (2) EXPONENT. -1 accounts for decimal point. int msd; // Position of most significant digit in res or indication its outside res. boolean hasPoint = false; if (truncated) { msd = -1; Loading @@ -261,16 +240,14 @@ public class CalculatorResult extends TextView { } if (msd < maxDigs - 1 && msd >= 0) { // TYPE (1) EXPONENT computation and transformation: // Leading digit is in display window. // Use standard calculator scientific notation // with one digit to the left of the decimal point. // Insert decimal point and delete leading zeroes. // Leading digit is in display window. Use standard calculator scientific notation // with one digit to the left of the decimal point. Insert decimal point and // delete leading zeroes. String fraction = res.substring(msd + 1, resLen); res = (negative ? "-" : "") + res.substring(msd, msd+1) + "." + fraction; res = (negative ? "-" : "") + res.substring(msd, msd+1) + "." + fraction; exp += resLen - msd - 1; // Original exp was correct for decimal point at right // of fraction. Adjust by length of fraction. // Original exp was correct for decimal point at right of fraction. // Adjust by length of fraction. resLen = res.length(); hasPoint = true; } Loading @@ -279,8 +256,7 @@ public class CalculatorResult extends TextView { String expAsString = Integer.toString(exp); int expDigits = expAsString.length(); int dropDigits = expDigits + 1; // Drop digits even if there is room. // Otherwise the scrolling gets jumpy. // Drop digits even if there is room. Otherwise the scrolling gets jumpy. if (dropDigits >= resLen - 1) { dropDigits = Math.max(resLen - 2, 0); // Jumpy is better than no mantissa. Loading @@ -289,11 +265,9 @@ public class CalculatorResult extends TextView { // Special handling for TYPE(2) EXPONENT: exp += dropDigits; expAsString = Integer.toString(exp); // Adjust for digits we are about to drop // to drop to make room for exponent. // This can affect the room we have for the // mantissa. We adjust only for positive exponents, // when it could otherwise result in a truncated // Adjust for digits we are about to drop to drop to make room for exponent. // This can affect the room we have for the mantissa. We adjust only for // positive exponents, when it could otherwise result in a truncated // displayed result. if (exp > 0 && expAsString.length() > expDigits) { // ++expDigits; (dead code) Loading @@ -315,10 +289,8 @@ public class CalculatorResult extends TextView { final boolean truncated[] = new boolean[1]; final boolean negative[] = new boolean[1]; final int requested_prec[] = {pos}; final String raw_res = mEvaluator.getString(requested_prec, maxSize, truncated, negative); return formatResult(raw_res, requested_prec[0], maxSize, truncated[0], negative[0]); final String raw_res = mEvaluator.getString(requested_prec, maxSize, truncated, negative); return formatResult(raw_res, requested_prec[0], maxSize, truncated[0], negative[0]); } // Return entire result (within reason) up to current displayed precision. Loading @@ -326,16 +298,14 @@ public class CalculatorResult extends TextView { if (!mValid) return ""; if (!mScrollable) return getText().toString(); int currentCharPos = getCurrentCharPos(); return KeyMaps.translateResult( getFormattedResult(currentCharPos, MAX_COPY_SIZE)); return KeyMaps.translateResult(getFormattedResult(currentCharPos, MAX_COPY_SIZE)); } public boolean fullTextIsExact() { BoundedRational rat = mEvaluator.getRational(); int currentCharPos = getCurrentCharPos(); if (currentCharPos == -1) { // Suppressing decimal point; still showing all // integral digits. // Suppressing decimal point; still showing all integral digits. currentCharPos = 0; } // TODO: Could handle scientific notation cases better; Loading @@ -345,19 +315,16 @@ public class CalculatorResult extends TextView { // May be called asynchronously from non-UI thread. int getMaxChars() { // We only use 2/3 of the available space, since the // left 1/3 of the result is not visible when it is shown // in large size. // We only use 2/3 of the available space, since the left 1/3 of the result is not // visible when it is shown in large size. int result; synchronized(mWidthLock) { result = 2 * mWidthConstraint / (3 * mCharWidth); // We can apparently finish evaluating before // onMeasure in CalculatorText has been called, in // which case we get 0 or -1 as the width constraint. // We can apparently finish evaluating before onMeasure in CalculatorText has been // called, in which case we get 0 or -1 as the width constraint. } if (result <= 0) { // Return something conservatively big, to force sufficient // evaluation. // Return something conservatively big, to force sufficient evaluation. return MAX_WIDTH; } else { return result; Loading Loading @@ -412,8 +379,7 @@ public class CalculatorResult extends TextView { // Copy support: private ActionMode.Callback mCopyActionModeCallback = new ActionMode.Callback() { private ActionMode.Callback mCopyActionModeCallback = new ActionMode.Callback() { @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { MenuInflater inflater = mode.getMenuInflater(); Loading Loading @@ -461,19 +427,14 @@ public class CalculatorResult extends TextView { private void copyContent() { final CharSequence text = getFullText(); ClipboardManager clipboard = (ClipboardManager) getContext().getSystemService( Context.CLIPBOARD_SERVICE); // We include a tag URI, to allow us to recognize our // own results and handle them specially. ClipData.Item newItem = new ClipData.Item(text, null, mEvaluator.capture()); String[] mimeTypes = new String[] {ClipDescription.MIMETYPE_TEXT_PLAIN}; ClipData cd = new ClipData("calculator result", mimeTypes, newItem); (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE); // We include a tag URI, to allow us to recognize our own results and handle them // specially. ClipData.Item newItem = new ClipData.Item(text, null, mEvaluator.capture()); String[] mimeTypes = new String[] {ClipDescription.MIMETYPE_TEXT_PLAIN}; ClipData cd = new ClipData("calculator result", mimeTypes, newItem); clipboard.setPrimaryClip(cd); Toast.makeText(getContext(), R.string.text_copied_toast, Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(), R.string.text_copied_toast, Toast.LENGTH_SHORT).show(); } }