上图:
需求:
-
宫格布局(宽高一致,在屏幕上高度始终更随宽度变化)
-
图片在上文字在下布局
-
可以控制图片的宽高
布局完成,废话不多说直接上代码:
/**
* 时 间 : 2019/7/22 0022
* 操作人 : yzhg
* 版 本 :
* 描 述 :
*
*
* <declare-styleable name="HeightCustTextView">
* <attr name="leftDrawable" format="reference" />
* <attr name="leftDrawableWidth" format="dimension" />
* <attr name="leftDrawableHeight" format="dimension" />
* <attr name="rightDrawable" format="reference" />
* <attr name="rightDrawableWidth" format="dimension" />
* <attr name="rightDrawableHeight" format="dimension" />
* <attr name="topDrawable" format="reference" />
* <attr name="topDrawableWidth" format="dimension" />
* <attr name="topDrawableHeight" format="dimension" />
* </declare-styleable>
*
*
*/
public class HeightCustTextView extends AppCompatTextView {
private Drawable drawableLeft;
private Drawable drawableRight;
private Drawable drawableTop;
private int leftWidth;
private int rightWidth;
private int topWidth;
private int leftHeight;
private int rightHeight;
private int topHeight;
private Context mContext;
public HeightCustTextView(Context context) {
super(context, null);
this.mContext = context;
}
public HeightCustTextView(Context context, AttributeSet attrs) {
super(context, attrs, 0);
this.mContext = context;
init(context, attrs);
}
public HeightCustTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext = context;
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HeightCustTextView);
drawableLeft = typedArray.getDrawable(R.styleable.HeightCustTextView_leftDrawable);
drawableRight = typedArray.getDrawable(R.styleable.HeightCustTextView_rightDrawable);
drawableTop = typedArray.getDrawable(R.styleable.HeightCustTextView_topDrawable);
if (drawableLeft != null) {
leftWidth = typedArray.getDimensionPixelOffset(R.styleable.HeightCustTextView_leftDrawableWidth, dip2px(context, 20));
leftHeight = typedArray.getDimensionPixelOffset(R.styleable.HeightCustTextView_leftDrawableHeight, dip2px(context, 20));
}
if (drawableRight != null) {
rightWidth = typedArray.getDimensionPixelOffset(R.styleable.HeightCustTextView_rightDrawableWidth, dip2px(context, 20));
rightHeight = typedArray.getDimensionPixelOffset(R.styleable.HeightCustTextView_rightDrawableHeight, dip2px(context, 20));
}
if (drawableTop != null) {
topWidth = typedArray.getDimensionPixelOffset(R.styleable.HeightCustTextView_topDrawableWidth, dip2px(context, 20));
topHeight = typedArray.getDimensionPixelOffset(R.styleable.HeightCustTextView_topDrawableHeight, dip2px(context, 20));
}
}
public int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec); //获取宽的模式
int heightMode = MeasureSpec.getMode(heightMeasureSpec); //获取高的模式
int heightSize = MeasureSpec.getSize(heightMeasureSpec); //获取高的尺寸
int widthSize = MeasureSpec.getSize(widthMeasureSpec); //获取宽的尺寸
//重新测量高度,将宽度赋值给高度
heightMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);
//重新设置左侧图片的宽高
if (drawableLeft != null) {
drawableLeft.setBounds(0, 0, leftWidth, leftHeight);
}
//重新设置右侧图片的宽高
if (drawableRight != null) {
drawableRight.setBounds(0, 0, rightWidth, rightHeight);
}
//重新设置上面图片的宽高
if (drawableTop != null) {
drawableTop.setBounds(0, 0, topWidth, topHeight);
}
//保存测量宽度和测量高度
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
// 获取TextView的Drawable对象,返回的数组长度应该是4,对应左上右下
Drawable[] drawables = getCompoundDrawables();
Drawable drawable = drawables[0];
if (drawable != null) {
// 当左边Drawable的不为空时,测量要绘制文本的宽度
float textWidth = getPaint().measureText(getText().toString());
int drawablePadding = getCompoundDrawablePadding();
int drawableWidth = drawable.getIntrinsicWidth();
// 计算总宽度(文本宽度 + drawablePadding + drawableWidth)
float bodyWidth = textWidth + drawablePadding + drawableWidth;
// 移动画布开始绘制的X轴
canvas.translate((getWidth() - bodyWidth) / 2, 0);
} else if ((drawable = drawables[1]) != null) {
// 否则如果上边的Drawable不为空时,获取文本的高度
Rect rect = new Rect();
getPaint().getTextBounds(getText().toString(), 0, getText().toString().length(), rect);
float textHeight = rect.height();
int drawablePadding = getCompoundDrawablePadding();
int drawableHeight = drawable.getIntrinsicHeight();
// 计算总高度(文本高度 + drawablePadding + drawableHeight)
float bodyHeight = textHeight + drawablePadding + drawableHeight;
// 移动画布开始绘制的Y轴
canvas.translate(0, (getHeight() - bodyHeight) / 2);
}
super.onDraw(canvas);
this.setCompoundDrawables(drawableLeft, drawableTop, drawableRight, null);
}
/**
* 设置左侧图片并重绘
*/
public void setDrawableLeft(Drawable drawableLeft) {
this.drawableLeft = drawableLeft;
invalidate();
}
/**
* 设置左侧图片并重绘
*/
public void setDrawableLeft(int drawableLeftRes) {
this.drawableLeft = mContext.getResources().getDrawable(drawableLeftRes);
invalidate();
}
/**
* 设置右侧图片并重绘
*/
public void setDrawableRight(Drawable drawableRight) {
this.drawableRight = drawableLeft;
invalidate();
}
/**
* 设置右侧图片并重绘
*/
public void setDrawableRight(int drawableRightRes) {
this.drawableRight = mContext.getResources().getDrawable(drawableRightRes);
invalidate();
}
/**
* 设置上部图片并重绘
*/
public void setDrawable(Drawable drawableTop) {
this.drawableTop = drawableTop;
invalidate();
}
/**
* 设置右侧图片并重绘
*/
public void setDrawableTop(int drawableTopRes) {
this.drawableTop = mContext.getResources().getDrawable(drawableTopRes);
invalidate();
}
}
styles:
<declare-styleable name="HeightCustTextView">
<attr name="leftDrawable" format="reference" />
<attr name="leftDrawableWidth" format="dimension" />
<attr name="leftDrawableHeight" format="dimension" />
<attr name="rightDrawable" format="reference" />
<attr name="rightDrawableWidth" format="dimension" />
<attr name="rightDrawableHeight" format="dimension" />
<attr name="topDrawable" format="reference" />
<attr name="topDrawableWidth" format="dimension" />
<attr name="topDrawableHeight" format="dimension" />
</declare-styleable>
参考xml布局(外层使用的是 ConstraintLayout )
<com.yzhg.ai.ui.weight.HeightCustTextView
android:id="@+id/hTvPassengerFlowInfo"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_8"
android:layout_marginEnd="@dimen/dp_1"
android:background="@color/color_FFFFFF"
android:drawablePadding="@dimen/dp_8"
android:gravity="center_horizontal"
android:text="@string/passenger_flow_info"
android:textSize="@dimen/default12"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/hTvHotspotAnalysis"
app:layout_constraintTop_toBottomOf="@+id/tvDataReport"
app:topDrawable="@mipmap/passenger_flow"
app:topDrawableHeight="@dimen/dp_24"
app:topDrawableWidth="@dimen/dp_24" />
必须设置:
android:gravity="center_horizontal"