Advertisement
Guest User

Untitled

a guest
Jun 23rd, 2017
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.70 KB | None | 0 0
  1. import android.annotation.TargetApi;
  2. import android.content.Context;
  3. import android.graphics.Bitmap;
  4. import android.graphics.Canvas;
  5. import android.graphics.DrawFilter;
  6. import android.graphics.Matrix;
  7. import android.graphics.Paint;
  8. import android.graphics.Path;
  9. import android.graphics.Picture;
  10. import android.graphics.PorterDuff;
  11. import android.graphics.Rect;
  12. import android.graphics.RectF;
  13. import android.graphics.Region;
  14. import android.os.Build;
  15. import android.support.annotation.NonNull;
  16. import android.support.annotation.Nullable;
  17. import android.support.annotation.RequiresApi;
  18. import android.support.design.widget.TextInputLayout;
  19. import android.util.AttributeSet;
  20.  
  21. import java.lang.reflect.Field;
  22. import java.lang.reflect.InvocationTargetException;
  23. import java.lang.reflect.Method;
  24.  
  25. /**
  26. * A TextInputLayout that draws multiline text.
  27. * <p>
  28. * api18+ is required, because versions below use its own texture for drawing, and it calls
  29. * {@code new Canvas()} which is too difficult to git rid of.
  30. */
  31. @RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
  32. public class MultilineHintTextInputLayout extends TextInputLayout {
  33. private static final String TAG = "MlHintTextInputLayout";
  34.  
  35. public MultilineHintTextInputLayout(Context context) {
  36. super(context);
  37. init();
  38. }
  39.  
  40. public MultilineHintTextInputLayout(Context context, AttributeSet attrs) {
  41. super(context, attrs);
  42. init();
  43. }
  44.  
  45. public MultilineHintTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
  46. super(context, attrs, defStyleAttr);
  47. init();
  48. }
  49.  
  50. private CanvasWrapper mCanvasWrapper = new CanvasWrapper();
  51. private Object mCollapsingTextHelper = null;
  52. private Method mCollapsingTextHelper_draw = null;
  53. private Field mHintEnabledField = null;
  54. private Field mCollapsingTextHelper_mText = null;
  55. private Field mCollapsingTextHelper_mTextToDraw = null;
  56.  
  57. private void init() {
  58. mCanvasWrapper.setCanvas(null);
  59. try {
  60. mHintEnabledField = TextInputLayout.class.getDeclaredField("mHintEnabled");
  61. mHintEnabledField.setAccessible(true);
  62.  
  63. final Field field = TextInputLayout.class.getDeclaredField("mCollapsingTextHelper");
  64. field.setAccessible(true);
  65. mCollapsingTextHelper = field.get(this);
  66.  
  67. final Class klassCollapsingTextHelper = Class.forName("android.support.design.widget.CollapsingTextHelper");
  68. //noinspection unchecked
  69. mCollapsingTextHelper_draw = klassCollapsingTextHelper.getDeclaredMethod("draw", Canvas.class);
  70. mCollapsingTextHelper_mText = klassCollapsingTextHelper.getDeclaredField("mText");
  71. mCollapsingTextHelper_mTextToDraw = klassCollapsingTextHelper.getDeclaredField("mTextToDraw");
  72. mCollapsingTextHelper_mText.setAccessible(true);
  73. mCollapsingTextHelper_mTextToDraw.setAccessible(true);
  74.  
  75. } catch (IllegalAccessException | NoSuchFieldException | NoSuchMethodException | ClassNotFoundException ex) {
  76. mCanvasWrapper = null;
  77. mCollapsingTextHelper = null;
  78. mCollapsingTextHelper_draw = null;
  79. mHintEnabledField = null;
  80. mCollapsingTextHelper_mText = null;
  81. mCollapsingTextHelper_mTextToDraw = null;
  82. }
  83. }
  84.  
  85. @Override
  86. public void draw(Canvas canvas) {
  87. if (mCollapsingTextHelper == null) {
  88. super.draw(canvas);
  89. return;
  90. }
  91. try {
  92. final boolean hint = (boolean) mHintEnabledField.get(this);
  93. if (hint)
  94. mHintEnabledField.set(this, false);
  95. super.draw(canvas);
  96. if (hint) {
  97. mCollapsingTextHelper_mTextToDraw.set(mCollapsingTextHelper, mCollapsingTextHelper_mText.get(mCollapsingTextHelper));
  98. mHintEnabledField.set(this, true);
  99. mCanvasWrapper.setCanvas(canvas);
  100. mCollapsingTextHelper_draw.invoke(mCollapsingTextHelper, mCanvasWrapper);
  101. mCanvasWrapper.setCanvas(null); // do not hold a ref
  102. }
  103. } catch (IllegalAccessException | InvocationTargetException ex) {
  104. mCanvasWrapper = null;
  105. mCollapsingTextHelper = null;
  106. mCollapsingTextHelper_draw = null;
  107. mHintEnabledField = null;
  108. mCollapsingTextHelper_mText = null;
  109. mCollapsingTextHelper_mTextToDraw = null;
  110.  
  111. // failed, try again with super only.
  112. postInvalidate();
  113. }
  114. }
  115.  
  116. private static final class CanvasWrapper extends Canvas {
  117. private boolean mConstructed = false;
  118. // this dummy canvas is just for super's c-tor...
  119. private Canvas mCanvas = null;
  120.  
  121. CanvasWrapper() {
  122. super();
  123. mConstructed = true;
  124. }
  125.  
  126. void setCanvas(Canvas canvas) {
  127. mCanvas = canvas;
  128. }
  129.  
  130. private int nextNewLineAt(@NonNull CharSequence text, int start, int end) {
  131. while (start < end) {
  132. if (text.charAt(start) == '\n')
  133. return start;
  134. ++start;
  135. }
  136. return end;
  137. }
  138.  
  139. // only this one is used
  140. @Override
  141. public void drawText(@NonNull CharSequence text, int start, int end, float x, float y, @NonNull Paint paint) {
  142. // Log.d(TAG, "drawText(): size = " + paint.measureText(text, start, end) + ", text = \"" + text + "\"");
  143. final float spacing = paint.getFontSpacing();
  144. while (start < end) {
  145. final int newline = nextNewLineAt(text, start, end);
  146. // Log.d(TAG, "drawText(): y = " + y + ", size = " + paint.measureText(text, start, end) + ", subSequence = \"" + text.subSequence(start, end) + "\"");
  147. mCanvas.drawText(text, start, newline, x, y, paint);
  148. y += spacing;
  149. start = newline + 1;
  150. }
  151. }
  152.  
  153. @Override
  154. public boolean isHardwareAccelerated() {
  155. return mConstructed ? mCanvas.isHardwareAccelerated() : super.isHardwareAccelerated();
  156. }
  157.  
  158. @Override
  159. public void setBitmap(@Nullable Bitmap bitmap) {
  160. mCanvas.setBitmap(bitmap);
  161. }
  162.  
  163. @Override
  164. public boolean isOpaque() {
  165. return mCanvas.isOpaque();
  166. }
  167.  
  168. @Override
  169. public int getWidth() {
  170. return mCanvas.getWidth();
  171. }
  172.  
  173. @Override
  174. public int getHeight() {
  175. return mCanvas.getHeight();
  176. }
  177.  
  178. @Override
  179. public int getDensity() {
  180. return mCanvas.getDensity();
  181. }
  182.  
  183. @Override
  184. public void setDensity(int density) {
  185. mCanvas.setDensity(density);
  186. }
  187.  
  188. @Override
  189. public int getMaximumBitmapWidth() {
  190. return mCanvas.getMaximumBitmapWidth();
  191. }
  192.  
  193. @Override
  194. public int getMaximumBitmapHeight() {
  195. return mCanvas.getMaximumBitmapHeight();
  196. }
  197.  
  198. @Override
  199. public int save() {
  200. return mCanvas.save();
  201. }
  202.  
  203. @Override
  204. public int save(int saveFlags) {
  205. return mCanvas.save(saveFlags);
  206. }
  207.  
  208. @Override
  209. public int saveLayer(@Nullable RectF bounds, @Nullable Paint paint, int saveFlags) {
  210. return mCanvas.saveLayer(bounds, paint, saveFlags);
  211. }
  212.  
  213. @Override
  214. public int saveLayer(@Nullable RectF bounds, @Nullable Paint paint) {
  215. return mCanvas.saveLayer(bounds, paint);
  216. }
  217.  
  218. @Override
  219. public int saveLayer(float left, float top, float right, float bottom, @Nullable Paint paint, int saveFlags) {
  220. return mCanvas.saveLayer(left, top, right, bottom, paint, saveFlags);
  221. }
  222.  
  223. @Override
  224. public int saveLayer(float left, float top, float right, float bottom, @Nullable Paint paint) {
  225. return mCanvas.saveLayer(left, top, right, bottom, paint);
  226. }
  227.  
  228. @Override
  229. public int saveLayerAlpha(@Nullable RectF bounds, int alpha, int saveFlags) {
  230. return mCanvas.saveLayerAlpha(bounds, alpha, saveFlags);
  231. }
  232.  
  233. @Override
  234. public int saveLayerAlpha(@Nullable RectF bounds, int alpha) {
  235. return mCanvas.saveLayerAlpha(bounds, alpha);
  236. }
  237.  
  238. @Override
  239. public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha, int saveFlags) {
  240. return mCanvas.saveLayerAlpha(left, top, right, bottom, alpha, saveFlags);
  241. }
  242.  
  243. @Override
  244. public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha) {
  245. return mCanvas.saveLayerAlpha(left, top, right, bottom, alpha);
  246. }
  247.  
  248. @Override
  249. public void restore() {
  250. mCanvas.restore();
  251. }
  252.  
  253. @Override
  254. public int getSaveCount() {
  255. return mCanvas.getSaveCount();
  256. }
  257.  
  258. @Override
  259. public void restoreToCount(int saveCount) {
  260. mCanvas.restoreToCount(saveCount);
  261. }
  262.  
  263. @Override
  264. public void translate(float dx, float dy) {
  265. mCanvas.translate(dx, dy);
  266. }
  267.  
  268. @Override
  269. public void scale(float sx, float sy) {
  270. mCanvas.scale(sx, sy);
  271. }
  272.  
  273. @Override
  274. public void rotate(float degrees) {
  275. mCanvas.rotate(degrees);
  276. }
  277.  
  278. @Override
  279. public void skew(float sx, float sy) {
  280. mCanvas.skew(sx, sy);
  281. }
  282.  
  283. @Override
  284. public void concat(@Nullable Matrix matrix) {
  285. mCanvas.concat(matrix);
  286. }
  287.  
  288. @Override
  289. public void setMatrix(@Nullable Matrix matrix) {
  290. mCanvas.setMatrix(matrix);
  291. }
  292.  
  293. @Override
  294. @Deprecated
  295. public void getMatrix(@NonNull Matrix ctm) {
  296. mCanvas.getMatrix(ctm);
  297. }
  298.  
  299. @Override
  300. public boolean clipRect(@NonNull RectF rect, @NonNull Region.Op op) {
  301. return mCanvas.clipRect(rect, op);
  302. }
  303.  
  304. @Override
  305. public boolean clipRect(@NonNull Rect rect, @NonNull Region.Op op) {
  306. return mCanvas.clipRect(rect, op);
  307. }
  308.  
  309. @Override
  310. public boolean clipRect(@NonNull RectF rect) {
  311. return mCanvas.clipRect(rect);
  312. }
  313.  
  314. @Override
  315. public boolean clipRect(@NonNull Rect rect) {
  316. return mCanvas.clipRect(rect);
  317. }
  318.  
  319. @Override
  320. public boolean clipRect(float left, float top, float right, float bottom, @NonNull Region.Op op) {
  321. return mCanvas.clipRect(left, top, right, bottom, op);
  322. }
  323.  
  324. @Override
  325. public boolean clipRect(float left, float top, float right, float bottom) {
  326. return mCanvas.clipRect(left, top, right, bottom);
  327. }
  328.  
  329. @Override
  330. public boolean clipRect(int left, int top, int right, int bottom) {
  331. return mCanvas.clipRect(left, top, right, bottom);
  332. }
  333.  
  334. @Override
  335. public boolean clipPath(@NonNull Path path, @NonNull Region.Op op) {
  336. return mCanvas.clipPath(path, op);
  337. }
  338.  
  339. @Override
  340. public boolean clipPath(@NonNull Path path) {
  341. return mCanvas.clipPath(path);
  342. }
  343.  
  344. @Override
  345. @Deprecated
  346. public boolean clipRegion(@NonNull Region region, @NonNull Region.Op op) {
  347. return mCanvas.clipRegion(region, op);
  348. }
  349.  
  350. @Override
  351. @Deprecated
  352. public boolean clipRegion(@NonNull Region region) {
  353. return mCanvas.clipRegion(region);
  354. }
  355.  
  356. @Nullable
  357. @Override
  358. public DrawFilter getDrawFilter() {
  359. return mCanvas.getDrawFilter();
  360. }
  361.  
  362. @Override
  363. public void setDrawFilter(@Nullable DrawFilter filter) {
  364. mCanvas.setDrawFilter(filter);
  365. }
  366.  
  367. @Override
  368. public boolean quickReject(@NonNull RectF rect, @NonNull EdgeType type) {
  369. return mCanvas.quickReject(rect, type);
  370. }
  371.  
  372. @Override
  373. public boolean quickReject(@NonNull Path path, @NonNull EdgeType type) {
  374. return mCanvas.quickReject(path, type);
  375. }
  376.  
  377. @Override
  378. public boolean quickReject(float left, float top, float right, float bottom, @NonNull EdgeType type) {
  379. return mCanvas.quickReject(left, top, right, bottom, type);
  380. }
  381.  
  382. @Override
  383. public boolean getClipBounds(@Nullable Rect bounds) {
  384. return mCanvas.getClipBounds(bounds);
  385. }
  386.  
  387. @Override
  388. public void drawRGB(int r, int g, int b) {
  389. mCanvas.drawRGB(r, g, b);
  390. }
  391.  
  392. @Override
  393. public void drawARGB(int a, int r, int g, int b) {
  394. mCanvas.drawARGB(a, r, g, b);
  395. }
  396.  
  397. @Override
  398. public void drawColor(int color) {
  399. mCanvas.drawColor(color);
  400. }
  401.  
  402. @Override
  403. public void drawColor(int color, @NonNull PorterDuff.Mode mode) {
  404. mCanvas.drawColor(color, mode);
  405. }
  406.  
  407. @Override
  408. public void drawPaint(@NonNull Paint paint) {
  409. mCanvas.drawPaint(paint);
  410. }
  411.  
  412. @Override
  413. public void drawPoints(float[] pts, int offset, int count, @NonNull Paint paint) {
  414. mCanvas.drawPoints(pts, offset, count, paint);
  415. }
  416.  
  417. @Override
  418. public void drawPoints(@NonNull float[] pts, @NonNull Paint paint) {
  419. mCanvas.drawPoints(pts, paint);
  420. }
  421.  
  422. @Override
  423. public void drawPoint(float x, float y, @NonNull Paint paint) {
  424. mCanvas.drawPoint(x, y, paint);
  425. }
  426.  
  427. @Override
  428. public void drawLine(float startX, float startY, float stopX, float stopY, @NonNull Paint paint) {
  429. mCanvas.drawLine(startX, startY, stopX, stopY, paint);
  430. }
  431.  
  432. @Override
  433. public void drawLines(@NonNull float[] pts, int offset, int count, @NonNull Paint paint) {
  434. mCanvas.drawLines(pts, offset, count, paint);
  435. }
  436.  
  437. @Override
  438. public void drawLines(@NonNull float[] pts, @NonNull Paint paint) {
  439. mCanvas.drawLines(pts, paint);
  440. }
  441.  
  442. @Override
  443. public void drawRect(@NonNull RectF rect, @NonNull Paint paint) {
  444. mCanvas.drawRect(rect, paint);
  445. }
  446.  
  447. @Override
  448. public void drawRect(@NonNull Rect r, @NonNull Paint paint) {
  449. mCanvas.drawRect(r, paint);
  450. }
  451.  
  452. @Override
  453. public void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint) {
  454. mCanvas.drawRect(left, top, right, bottom, paint);
  455. }
  456.  
  457. @Override
  458. public void drawOval(@NonNull RectF oval, @NonNull Paint paint) {
  459. mCanvas.drawOval(oval, paint);
  460. }
  461.  
  462. @Override
  463. public void drawOval(float left, float top, float right, float bottom, @NonNull Paint paint) {
  464. mCanvas.drawOval(left, top, right, bottom, paint);
  465. }
  466.  
  467. @Override
  468. public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
  469. mCanvas.drawCircle(cx, cy, radius, paint);
  470. }
  471.  
  472. @Override
  473. public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint) {
  474. mCanvas.drawArc(oval, startAngle, sweepAngle, useCenter, paint);
  475. }
  476.  
  477. @Override
  478. public void drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint) {
  479. mCanvas.drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
  480. }
  481.  
  482. @Override
  483. public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) {
  484. mCanvas.drawRoundRect(rect, rx, ry, paint);
  485. }
  486.  
  487. @Override
  488. public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, @NonNull Paint paint) {
  489. mCanvas.drawRoundRect(left, top, right, bottom, rx, ry, paint);
  490. }
  491.  
  492. @Override
  493. public void drawPath(@NonNull Path path, @NonNull Paint paint) {
  494. mCanvas.drawPath(path, paint);
  495. }
  496.  
  497. @Override
  498. public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) {
  499. mCanvas.drawBitmap(bitmap, left, top, paint);
  500. }
  501.  
  502. @Override
  503. public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst, @Nullable Paint paint) {
  504. mCanvas.drawBitmap(bitmap, src, dst, paint);
  505. }
  506.  
  507. @Override
  508. public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst, @Nullable Paint paint) {
  509. mCanvas.drawBitmap(bitmap, src, dst, paint);
  510. }
  511.  
  512. @Override
  513. @Deprecated
  514. public void drawBitmap(@NonNull int[] colors, int offset, int stride, float x, float y, int width, int height, boolean hasAlpha, @Nullable Paint paint) {
  515. mCanvas.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint);
  516. }
  517.  
  518. @Override
  519. @Deprecated
  520. public void drawBitmap(@NonNull int[] colors, int offset, int stride, int x, int y, int width, int height, boolean hasAlpha, @Nullable Paint paint) {
  521. mCanvas.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint);
  522. }
  523.  
  524. @Override
  525. public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) {
  526. mCanvas.drawBitmap(bitmap, matrix, paint);
  527. }
  528.  
  529. @Override
  530. public void drawBitmapMesh(@NonNull Bitmap bitmap, int meshWidth, int meshHeight, @NonNull float[] verts, int vertOffset, @Nullable int[] colors, int colorOffset, @Nullable Paint paint) {
  531. mCanvas.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset, colors, colorOffset, paint);
  532. }
  533.  
  534. @Override
  535. public void drawVertices(@NonNull VertexMode mode, int vertexCount, @NonNull float[] verts, int vertOffset, @Nullable float[] texs, int texOffset, @Nullable int[] colors, int colorOffset, @Nullable short[] indices, int indexOffset, int indexCount, @NonNull Paint paint) {
  536. mCanvas.drawVertices(mode, vertexCount, verts, vertOffset, texs, texOffset, colors, colorOffset, indices, indexOffset, indexCount, paint);
  537. }
  538.  
  539. @Override
  540. public void drawText(@NonNull char[] text, int index, int count, float x, float y, @NonNull Paint paint) {
  541. mCanvas.drawText(text, index, count, x, y, paint);
  542. }
  543.  
  544. @Override
  545. public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
  546. mCanvas.drawText(text, x, y, paint);
  547. }
  548.  
  549. @Override
  550. public void drawText(@NonNull String text, int start, int end, float x, float y, @NonNull Paint paint) {
  551. mCanvas.drawText(text, start, end, x, y, paint);
  552. }
  553.  
  554. @TargetApi(Build.VERSION_CODES.M)
  555. @Override
  556. public void drawTextRun(@NonNull char[] text, int index, int count, int contextIndex, int contextCount, float x, float y, boolean isRtl, @NonNull Paint paint) {
  557. mCanvas.drawTextRun(text, index, count, contextIndex, contextCount, x, y, isRtl, paint);
  558. }
  559.  
  560. @TargetApi(Build.VERSION_CODES.M)
  561. @Override
  562. public void drawTextRun(@NonNull CharSequence text, int start, int end, int contextStart, int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) {
  563. mCanvas.drawTextRun(text, start, end, contextStart, contextEnd, x, y, isRtl, paint);
  564. }
  565.  
  566. @Override
  567. @Deprecated
  568. public void drawPosText(@NonNull char[] text, int index, int count, @NonNull float[] pos, @NonNull Paint paint) {
  569. mCanvas.drawPosText(text, index, count, pos, paint);
  570. }
  571.  
  572. @Override
  573. @Deprecated
  574. public void drawPosText(@NonNull String text, @NonNull float[] pos, @NonNull Paint paint) {
  575. mCanvas.drawPosText(text, pos, paint);
  576. }
  577.  
  578. @Override
  579. public void drawTextOnPath(@NonNull char[] text, int index, int count, @NonNull Path path, float hOffset, float vOffset, @NonNull Paint paint) {
  580. mCanvas.drawTextOnPath(text, index, count, path, hOffset, vOffset, paint);
  581. }
  582.  
  583. @Override
  584. public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset, float vOffset, @NonNull Paint paint) {
  585. mCanvas.drawTextOnPath(text, path, hOffset, vOffset, paint);
  586. }
  587.  
  588. @Override
  589. public void drawPicture(@NonNull Picture picture) {
  590. mCanvas.drawPicture(picture);
  591. }
  592.  
  593. @Override
  594. public void drawPicture(@NonNull Picture picture, @NonNull RectF dst) {
  595. mCanvas.drawPicture(picture, dst);
  596. }
  597.  
  598. @Override
  599. public void drawPicture(@NonNull Picture picture, @NonNull Rect dst) {
  600. mCanvas.drawPicture(picture, dst);
  601. }
  602. }
  603. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement