上图:
在写计算器布局的时候需要用到这样的页面:
-
个人觉得最好的实现方式应该是RecycleView
-
其次可以采用表格布局(这个布局貌似很少使用)
-
可以用LinearLayout 嵌套 TextView
今天要说的就是LinearLayout 嵌套 TextView
但是此TextVIew 并非官方,而是我们自定义的View
代码飘一下:
/**
* 类 名: LineTextView
* 作 者: yzhg
* 创 建: 2018/9/20 0020
* 版 本: 1.0
* 历 史: (版本) 作者 时间 注释
* 描 述: 自定义TextView 用于实现计算器页面 绘制四边闲,减少布局
*
* <declare-styleable name="LineTextView">
* <attr name="mText" format="string" />
* <attr name="mTextColor" format="color" />
* <attr name="mTextSize" format="dimension" />
* <attr name="mTopLine" format="boolean" />
* <attr name="mBottomLine" format="boolean" />
* <attr name="mLeftLine" format="boolean" />
* <attr name="mRightLine" format="boolean" />
* <attr name="mLineWidth" format="dimension" />
* <attr name="mLineColor" format="color" />
* <attr name="mLineLeftColor" format="color" />
* <attr name="mLineRightColor" format="color" />
* <attr name="mLineTopColor" format="color" />
* <attr name="mLineBottomColor" format="color" />
* </declare-styleable>
*/
public class LineTextView extends View {
/**
* 需要绘制的文字
*/
private String mText;
/**
* 文本的颜色
*/
private int mTextColor;
/**
* 文本的大小
*/
private float mTextSize;
/**
* 作 者: yzhg
* 历 史: (版本) 1.0
* 描 述: 线的宽度
*/
private float mLineWidth;
/**
* 绘制时控制文本绘制的范围
*/
private Rect mBound;
private Paint mPaint;
private Context context;
private final int DEFAULT_SIZE = 14;
private float sroke_width = 1;
private int mLineColor;
private int mLineTopColor;
private int mLineBottomColor;
private int mLineLeftColor;
private int mLineRightColor;
private boolean topLine = false;
private boolean bottomLine = false;
private boolean leftLine = false;
private boolean rightLine = false;
public LineTextView(Context context) {
this(context, null);
}
public LineTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LineTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
initAttributes(context, attrs);
mPaint = new Paint();
mBound = new Rect();
mPaint.setTextSize(mTextSize);
mPaint.setColor(mTextColor);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAntiAlias(true);
//获取要绘制文字的宽高
mPaint.getTextBounds(mText, 0, mText.length(), mBound);
}
private void initAttributes(Context context, AttributeSet attrs) {
@SuppressLint({"CustomViewStyleable", "Recycle"})
TypedArray toolbarArray = context.obtainStyledAttributes(attrs, R.styleable.LineTextView);
mTextSize = toolbarArray.getDimension(R.styleable.LineTextView_mTextSize, DEFAULT_SIZE);
mLineWidth = toolbarArray.getDimension(R.styleable.LineTextView_mLineWidth, 0.5f);
mText = toolbarArray.getString(R.styleable.LineTextView_mText);
/*
* 作 者: yzhg
* 历 史: (版本) 1.0
* 描 述: 线的方向 top bottom left right all
*/
topLine = toolbarArray.getBoolean(R.styleable.LineTextView_mTopLine, false);
bottomLine = toolbarArray.getBoolean(R.styleable.LineTextView_mBottomLine, false);
leftLine = toolbarArray.getBoolean(R.styleable.LineTextView_mLeftLine, false);
rightLine = toolbarArray.getBoolean(R.styleable.LineTextView_mRightLine, false);
/*
* 作 者: yzhg
* 历 史: (版本) 1.0
* 描 述: 设置文字的颜色
*/
mTextColor = toolbarArray.getColor(R.styleable.LineTextView_mTextColor, context.getResources().getColor(R.color.color_000000));
/*
* 作 者: yzhg
* 历 史: (版本) 1.0
* 描 述: 设置线的颜色
*/
mLineColor = toolbarArray.getColor(R.styleable.LineTextView_mLineColor, context.getResources().getColor(R.color.color_CECED2));
mLineTopColor = toolbarArray.getColor(R.styleable.LineTextView_mLineTopColor, context.getResources().getColor(R.color.color_CECED2));
mLineBottomColor = toolbarArray.getColor(R.styleable.LineTextView_mLineBottomColor, context.getResources().getColor(R.color.color_CECED2));
mLineLeftColor = toolbarArray.getColor(R.styleable.LineTextView_mLineLeftColor, context.getResources().getColor(R.color.color_CECED2));
mLineRightColor = toolbarArray.getColor(R.styleable.LineTextView_mLineRightColor, context.getResources().getColor(R.color.color_CECED2));
toolbarArray.recycle();
}
/*
* 作 者: yzhg
* 历 史: (版本) 1.0
* 描 述: 测量布局
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec); //获取宽的模式
int heightMode = MeasureSpec.getMode(heightMeasureSpec); //获取高的模式
int widthSize = MeasureSpec.getSize(widthMeasureSpec); //获取宽的尺寸
int heightSize = MeasureSpec.getSize(heightMeasureSpec); //获取高的尺寸
int width;
int height;
if (widthMode == MeasureSpec.EXACTLY) {
//如果match_parent或者具体的值,直接赋值
width = widthSize;
} else {
//如果是wrap_content,我们要得到控件需要多大的尺寸
float textWidth = mBound.width(); //文本的宽度
//控件的宽度就是文本的宽度加上两边的内边距。内边距就是padding值,在构造方法执行完就被赋值
width = (int) (getPaddingLeft() + textWidth + getPaddingRight());
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else {
float textHeight = mBound.height();
height = (int) (getPaddingTop() + textHeight + getPaddingBottom());
}
//保存测量宽度和测量高度
setMeasuredDimension(width, height);
}
@Override
protected void onDraw(Canvas canvas) {
/*
* 作 者: yzhg
* 历 史: (版本) 1.0
* 描 述: 控件宽度/2 - 文字宽度/2
*/
float startX = getWidth() / 2 - mBound.width() / 2;
/*
* 作 者: yzhg
* 历 史: (版本) 1.0
* 描 述: 控件高度/2 + 文字高度/2,绘制文字从文字左下角开始,因此"+"
*/
float startY = getHeight() / 2 + mBound.height() / 2;
/*
* 作 者: yzhg
* 历 史: (版本) 1.0
* 描 述: 绘制文字
*/
mPaint.setColor(mTextColor);
canvas.drawText(mText, startX, startY, mPaint);
/*
* 作 者: yzhg
* 历 史: (版本) 1.0
* 描 述: 绘制边框
*/
// mPaint.setColor(mLineColor); //设置边框颜色
//绘制上方线
if (topLine) {
mPaint.setColor(mLineTopColor);
mPaint.setStrokeWidth(mLineWidth);
canvas.drawLine(0, 0, this.getWidth() - sroke_width, 0, mPaint);
}
//绘制下边框
if (bottomLine) {
mPaint.setColor(mLineBottomColor);
mPaint.setStrokeWidth(mLineWidth);
canvas.drawLine(0, this.getHeight() - sroke_width, this.getWidth() - sroke_width, this.getHeight() - sroke_width, mPaint);
}
//绘制左边框
if (leftLine) {
mPaint.setColor(mLineLeftColor);
mPaint.setStrokeWidth(mLineWidth);
canvas.drawLine(0, 0, 0, this.getHeight() - sroke_width, mPaint);
}
//绘制右边框
if (rightLine) {
mPaint.setColor(mLineRightColor);
mPaint.setStrokeWidth(mLineWidth);
canvas.drawLine(this.getWidth() - sroke_width, 0, this.getWidth() - sroke_width, this.getHeight() - sroke_width, mPaint);
}
super.onDraw(canvas);
}
public int dip2px(float dip) {
//获取屏幕的密度
float density = context.getResources().getDisplayMetrics().density;
return (int) (dip * density + 0.5f);
}
public float px2dip(float px) {
float density = context.getResources().getDisplayMetrics().density;
return px / density;
}
}
attrs:
<declare-styleable name="LineTextView">
<attr name="mText" format="string" />
<attr name="mTextColor" format="color" />
<attr name="mTextSize" format="dimension" />
<attr name="mTopLine" format="boolean" />
<attr name="mBottomLine" format="boolean" />
<attr name="mLeftLine" format="boolean" />
<attr name="mRightLine" format="boolean" />
<attr name="mLineWidth" format="dimension" />
<attr name="mLineColor" format="color" />
<attr name="mLineLeftColor" format="color" />
<attr name="mLineRightColor" format="color" />
<attr name="mLineTopColor" format="color" />
<attr name="mLineBottomColor" format="color" />
</declare-styleable>