總是覺得需求才是促進(jìn)成長的一大動力哈哈
由于本人之前是做網(wǎng)頁開發(fā)的绢片,對于標(biāo)簽的流式布局只需要在flex布局內(nèi)設(shè)置幾個屬性就能完成了滤馍。而轉(zhuǎn)了android之后卻沒有那么好用的屬性了,所以一直都想做一個android版的流式布局
(網(wǎng)上一搜一大堆底循,但還是想要自己實現(xiàn)一波)
公司有一個需求:添加一個獎勵標(biāo)簽纪蜒。效果圖如下:
實現(xiàn)思路很簡單:
1.在onMearsure中遍歷list,計算出控件需要占據(jù)的總高度
2.在onDraw中同理計算出每一個item的左上角位置此叠,調(diào)用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中設(shè)置
private int nowWidth;
private int nowHeight;
private int rectHeight; //矩形高度
//暴露給外邊設(shè)置item數(shù)據(jù)的方法
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);
//設(shè)置抗鋸齒
mPaint.setAntiAlias(true);
//設(shè)置防抖動
mPaint.setDither(true);
//設(shè)置填充方式
mPaint.setStyle(Paint.Style.FILL);
textPaint = new Paint();
textPaint.setColor(textColor);
//設(shè)置文本字體大小
textPaint.setTextSize(textSize);
//設(shè)置抗鋸齒
textPaint.setAntiAlias(true);
//設(shè)置防抖動
textPaint.setDither(true);
//設(shè)置填充方式
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();
//文字基準(zhǔn)線的下部距離-文字基準(zhǔn)線的上部距離 = 文字高度
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;
}
}
}
/**
* 傳入的參數(shù)分別為文本和矩形左上角橫縱坐標(biāo)灭袁,矩形寬度(矩形高度上面已經(jīng)計算好)和一個畫布
*/
@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);
}
}