2727 * 2、设置Drawable的大小 √
2828 * 3、文字居中,图片靠边居中 √
2929 * 4、多次setCompoundDrawablesRelative,图片会发生偏移 √
30- * 5、寻找一个合适的测量文字大小的时机,避免多次测量消耗性能 √
30+ * 5、寻找一个合适的测量文字大小的时机,避免多次测量 √
3131 * 6、在draw时,避免用取出旧的drawable的bounds绘制,需要预先取出并存储起来,还需要注意在存储bounds时是不是有平移过 √
32- * 7、
32+ * 7、foreground会受平移影响 √
33+ * 8、如果是只有hint没有Text需要也需要测量出文字大小√
3334 */
3435@ SuppressWarnings ({"UnusedReturnValue" , "unused" , "SameParameterValue" })
3536public class DrawableTextView extends AppCompatTextView {
@@ -51,7 +52,8 @@ public class DrawableTextView extends AppCompatTextView {
5152 private float mTextHeight ;
5253
5354 private boolean firstLayout ;
54- private boolean isCenter ; //Gravity是否是居中
55+ private boolean isCenterHorizontal ; //Gravity是否水平居中
56+ private boolean isCenterVertical ; //Gravity是否垂直居中
5557 private boolean enableCenterDrawables ; //drawable跟随文本居中
5658 private boolean enableTextInCenter ; //默认情况下文字与图片共同居中,开启后文字在最中间,图片紧挨
5759
@@ -108,8 +110,8 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto
108110 super .onLayout (changed , left , top , right , bottom );
109111 if (enableCenterDrawables ) {
110112 final int absoluteGravity = Gravity .getAbsoluteGravity (getGravity (), getLayoutDirection ());
111- isCenter = (absoluteGravity & Gravity .HORIZONTAL_GRAVITY_MASK ) == Gravity .CENTER_HORIZONTAL
112- || (absoluteGravity & Gravity .VERTICAL_GRAVITY_MASK ) == Gravity .CENTER_VERTICAL ;
113+ isCenterHorizontal = (absoluteGravity & Gravity .HORIZONTAL_GRAVITY_MASK ) == Gravity .CENTER_HORIZONTAL ;
114+ isCenterVertical = (absoluteGravity & Gravity .VERTICAL_GRAVITY_MASK ) == Gravity .CENTER_VERTICAL ;
113115 }
114116
115117 if (!firstLayout ) {
@@ -118,6 +120,7 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto
118120 }
119121 }
120122
123+
121124 protected void onFirstLayout (int left , int top , int right , int bottom ) {
122125 measureTextWidth ();
123126 measureTextHeight ();
@@ -129,7 +132,7 @@ protected void onFirstLayout(int left, int top, int right, int bottom) {
129132 @ Override
130133 protected void onDraw (Canvas canvas ) {
131134
132- if (enableCenterDrawables && isCenter ) {
135+ if (enableCenterDrawables && ( isCenterHorizontal | isCenterVertical ) ) {
133136
134137 //画布的偏移量
135138 int transX = 0 , transY = 0 ;
@@ -139,7 +142,9 @@ protected void onDraw(Canvas canvas) {
139142 int offset = (int ) calcOffset (POSITION .START );
140143 mDrawables [POSITION .START ].setBounds (bounds .left + offset , bounds .top ,
141144 bounds .right + offset , bounds .bottom );
142- transX -= (mDrawablesBounds [POSITION .START ].width () + getCompoundDrawablePadding ()) >> 1 ;
145+
146+ if (isCenterHorizontal )
147+ transX -= (mDrawablesBounds [POSITION .START ].width () + getCompoundDrawablePadding ()) >> 1 ;
143148 }
144149
145150 if (mDrawables [POSITION .TOP ] != null ) {
@@ -149,7 +154,8 @@ protected void onDraw(Canvas canvas) {
149154 mDrawables [POSITION .TOP ].setBounds (bounds .left , bounds .top + offset ,
150155 bounds .right , bounds .bottom + offset );
151156
152- transY -= (mDrawablesBounds [POSITION .TOP ].height () + getCompoundDrawablePadding ()) >> 1 ;
157+ if (isCenterVertical )
158+ transY -= (mDrawablesBounds [POSITION .TOP ].height () + getCompoundDrawablePadding ()) >> 1 ;
153159 }
154160
155161 if (mDrawables [POSITION .END ] != null ) {
@@ -158,7 +164,8 @@ protected void onDraw(Canvas canvas) {
158164 mDrawables [POSITION .END ].setBounds (bounds .left + offset , bounds .top ,
159165 bounds .right + offset , bounds .bottom );
160166
161- transX += (mDrawablesBounds [POSITION .END ].width () + getCompoundDrawablePadding ()) >> 1 ;
167+ if (isCenterHorizontal )
168+ transX += (mDrawablesBounds [POSITION .END ].width () + getCompoundDrawablePadding ()) >> 1 ;
162169 }
163170
164171 if (mDrawables [POSITION .BOTTOM ] != null ) {
@@ -167,7 +174,8 @@ protected void onDraw(Canvas canvas) {
167174 mDrawables [POSITION .BOTTOM ].setBounds (bounds .left , bounds .top + offset ,
168175 bounds .right , bounds .bottom + offset );
169176
170- transY += (mDrawablesBounds [POSITION .BOTTOM ].height () + getCompoundDrawablePadding ()) >> 1 ;
177+ if (isCenterVertical )
178+ transY += (mDrawablesBounds [POSITION .BOTTOM ].height () + getCompoundDrawablePadding ()) >> 1 ;
171179 }
172180
173181 if (enableTextInCenter ) {
@@ -176,10 +184,16 @@ protected void onDraw(Canvas canvas) {
176184 this .canvasTransY = transY ;
177185 }
178186 }
179-
180187 super .onDraw (canvas );
181188 }
182189
190+ @ Override
191+ public void onDrawForeground (Canvas canvas ) {
192+ //再次平移回去
193+ canvas .translate (-canvasTransX , -canvasTransY );
194+ super .onDrawForeground (canvas );
195+ }
196+
183197 /**
184198 * 计算drawable居中还需距离
185199 * 如果左右两边都有图片,左图片居中则需要加上右侧图片占用的空间{@link #getCompoundPaddingEnd()},其他同理
@@ -219,7 +233,13 @@ protected int getCanvasTransY() {
219233 protected void measureTextWidth () {
220234 final Rect textBounds = new Rect ();
221235 getLineBounds (0 , textBounds );
222- final float width = getPaint ().measureText (getText ().toString ());
236+ String text = "" ;
237+ if (getText () != null && getText ().length () > 0 ) {
238+ text = getText ().toString ();
239+ } else if (getHint () != null && getHint ().length () > 0 ) {
240+ text = getHint ().toString ();
241+ }
242+ final float width = getPaint ().measureText (text );
223243 final float maxWidth = textBounds .width ();
224244 mTextWidth = width <= maxWidth || maxWidth == 0 ? width : maxWidth ;
225245 }
@@ -228,7 +248,8 @@ protected void measureTextWidth() {
228248 * 获取文本的高度,通过{@link #getLineHeight}乘文本的行数
229249 */
230250 protected void measureTextHeight () {
231- if (getText ().length () > 0 )
251+ if ((getText () != null && getText ().length () > 0 )
252+ || (getHint () != null && getHint ().length () > 0 ))
232253 mTextHeight = getLineHeight () * getLineCount ();
233254 else
234255 mTextHeight = 0 ;
@@ -251,19 +272,27 @@ public void setText(CharSequence text, BufferType type) {
251272
252273 /**
253274 * 设置Drawable,并设置宽高
275+ * 默认大小为Drawable的{@link Drawable#getBounds()} ,
276+ * 如果Bounds宽高为0则,取Drawable的内部固定尺寸{@link Drawable#getIntrinsicHeight()}
254277 *
255278 * @param position {@link POSITION}
256279 * @param drawable Drawable
257- * @param width DX
258- * @param height DX
280+ * @param width Px
281+ * @param height Px
259282 */
260283 public void setDrawable (@ POSITION int position , @ Nullable Drawable drawable , @ Px int width , @ Px int height ) {
261284 mDrawables [position ] = drawable ;
262285 if (drawable != null ) {
263286 Rect bounds = new Rect ();
264287 if (width == -1 && height == -1 ) {
265- bounds .right = drawable .getIntrinsicWidth ();
266- bounds .bottom = drawable .getIntrinsicHeight ();
288+ if (drawable .getBounds ().width () > 0 && drawable .getBounds ().height () > 0 ) {
289+ //如果Bounds宽高大于0,则保持默认
290+ final Rect origin = drawable .getBounds ();
291+ bounds .set (origin .left , origin .top , origin .right , origin .bottom );
292+ } else {
293+ //否则取Drawable的内部大小
294+ bounds .set (0 , 0 , drawable .getIntrinsicWidth (), drawable .getIntrinsicHeight ());
295+ }
267296 } else {
268297 bounds .right = width ;
269298 bounds .bottom = height ;
@@ -317,15 +346,19 @@ private void storeDrawables(@Nullable Drawable start, @Nullable Drawable top, @N
317346 protected Drawable [] copyDrawables (boolean clearOffset ) {
318347 Drawable [] drawables = Arrays .copyOf (getDrawables (), 4 );
319348 //clear offset
320- if (clearOffset ) {
321- for (Drawable drawable : drawables ) {
322- if (drawable != null ) {
323- Rect bounds = drawable .getBounds ();
324- bounds .offset (-bounds .left , -bounds .top );
325- }
349+ if (clearOffset )
350+ clearOffset (drawables );
351+
352+ return drawables ;
353+ }
354+
355+ private void clearOffset (Drawable ... drawables ) {
356+ for (Drawable drawable : drawables ) {
357+ if (drawable != null ) {
358+ Rect bounds = drawable .getBounds ();
359+ bounds .offset (-bounds .left , -bounds .top );
326360 }
327361 }
328- return drawables ;
329362 }
330363
331364 protected int dp2px (float dpValue ) {
@@ -383,18 +416,28 @@ public DrawableTextView setDrawableBottom(Drawable drawableBottom) {
383416 return this ;
384417 }
385418
386- public void setEnableCenterDrawables (boolean enable ) {
419+ public DrawableTextView setEnableCenterDrawables (boolean enable ) {
420+ if (enableCenterDrawables ) {
421+ //清除之前的位移
422+ clearOffset (mDrawables );
423+ }
387424 this .enableCenterDrawables = enable ;
425+ return this ;
388426 }
389427
390- public void setEnableTextInCenter (boolean enable ) {
428+ public DrawableTextView setEnableTextInCenter (boolean enable ) {
391429 this .enableTextInCenter = enable ;
430+ return this ;
392431 }
393432
394433 public boolean isEnableTextInCenter () {
395434 return enableTextInCenter ;
396435 }
397436
437+ public boolean isEnableCenterDrawables () {
438+ return enableCenterDrawables ;
439+ }
440+
398441 public Drawable [] getDrawables () {
399442 return mDrawables ;
400443 }
0 commit comments