总是觉得需求才是促进成长的一大动力哈哈
由于本人之前是做网页开发的,对于标签的流式布局只需要在flex布局内设置几个属性就能完成了。而转了android之后却没有那么好用的属性了,所以一直都想做一个android版的流式布局
(网上一搜一大堆,但还是想要自己实现一波)
公司有一个需求:添加一个奖励标签。效果图如下:
image.png
实现思路很简单:
1.在onMearsure中遍历list,计算出控件需要占据的总高度
2.在onDraw中同理计算出每一个item的左上角位置,调用drawItem方法绘制出item
下面是源代码
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
public class CustomFlexLayout extends View {
private static final String TAG = "FlexLayout";
private Paint mPaint;
private Paint textPaint;
private Path mPath;
private List<String> list = new ArrayList<>();
private int marginV = 16;//绘制的item的纵向margin值
private int marginH = 10;//绘制的item的横向margin值
private int paddingV = 20;//绘制的item的纵向padding值
private int paddingH = 28;//绘制的item的横向padding值
private int radius = 4;//绘制的item四个角的半径
private int backColor = Color.parseColor("#f3f9ff");//绘制的item的背景颜色
private int textColor = Color.parseColor("#007aff");//绘制的item的背景颜色
private float textSize = 32f;
private int height;//控件高度,在onMeasure中计算得到
private int width;//控件宽度,在xml中设置
private int nowWidth;
private int nowHeight;
private int rectHeight; //矩形高度
//暴露给外边设置item数据的方法
public void setList(List<String> list) {
this.list = list;
requestLayout();
}
public CustomFlexLayout(Context context) {
this(context, null);
}
public CustomFlexLayout(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomFlexLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setColor(backColor);
//设置抗锯齿
mPaint.setAntiAlias(true);
//设置防抖动
mPaint.setDither(true);
//设置填充方式
mPaint.setStyle(Paint.Style.FILL);
textPaint = new Paint();
textPaint.setColor(textColor);
//设置文本字体大小
textPaint.setTextSize(textSize);
//设置抗锯齿
textPaint.setAntiAlias(true);
//设置防抖动
textPaint.setDither(true);
//设置填充方式
textPaint.setStyle(Paint.Style.FILL);
mPath = new Path();
rectHeight = marginV * 2 + paddingV * 2 + getFontHeight(textPaint);
nowHeight = 0;
nowWidth = 0;
}
private int getTextLength(String text) {
return (int) textPaint.measureText(text);
}
private int getRectWidth(String text) {
return marginH * 2 + paddingH * 2 + getTextLength(text);
}
private int getFontHeight(Paint paint) {
Paint.FontMetrics fm = paint.getFontMetrics();
//文字基准线的下部距离-文字基准线的上部距离 = 文字高度
return (int) -(fm.bottom + fm.top);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
nowWidth = 0;
nowHeight = rectHeight;
width = getMeasuredWidth();
int length;
for (int i=0;i<list.size();i++) {
length = getRectWidth(list.get(i));
if (nowWidth + length <= width) {
nowWidth += length;
}else {
nowWidth = length;
nowHeight += rectHeight;
}
}
height = nowHeight;
setMeasuredDimension(width, height);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
nowWidth = 0;
nowHeight = 0;
for (int i=0;i<list.size();i++) {
int length = getRectWidth(list.get(i));
Log.i(TAG, "text:" + list.get(i) + " length:" + length);
//还未满一行
if (nowWidth + length <= width) {
drawitem(list.get(i), nowWidth, nowHeight, getRectWidth(list.get(i)), canvas);
nowWidth += length;
}else /*满一行*/{
nowWidth = 0;
nowHeight += rectHeight;
drawitem(list.get(i), nowWidth, nowHeight, getRectWidth(list.get(i)), canvas);
nowWidth += length;
}
}
}
/**
* 传入的参数分别为文本和矩形左上角横纵坐标,矩形宽度(矩形高度上面已经计算好)和一个画布
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void drawitem(String text, int startX, int startY, int rectWidth, Canvas canvas) {
//Log.i(TAG, "text:" + text);
//绘制矩形背景
canvas.drawRoundRect(startX + marginH, startY + marginV, startX + rectWidth - marginH, startY + rectHeight - marginV, radius, radius, mPaint);
//绘制中心文字
canvas.drawText(text, startX + (rectWidth/2-getTextLength(text)/2),
startY + getFontHeight(textPaint)/2 + rectHeight/2, textPaint);
}
}
网友评论