前段时间因为工作的需求,研究了一下自定义View的一些相关绘制方法,要求在指定区域内绘制多个矩形,并且矩形之前不重叠,效果图如下
数据是由后台返回的,给出了具体的横坐标,然后去计算纵坐标,这里我抽出来相关的核心算法代码,分享一下
/ **
在固定区域绘制多个标签,已知标签的左上角X坐标,宽,高,求解每个标签的最优的左上角ÿ坐标
* /
{
int centerY = mMainRect.Height()/ 2; //绘制区域中心点Y.
int centerX = mMainRect.Width()/ 2; //绘制区域中心点X.
int maxH = mMainRect.Height() - 10;
int minH = 0;
int offsetY = 20; //建议标签到分时图上的点的最佳偏移量
int marginY = 2; //每个标签Y轴坐标最小间距
int颜色;
int lineColor;
int padding = 10;
List <MarketChangeBean> labelArr = new ArrayList <>();
for(MarketChangeBean bean:mBigChangeBeans){
int y = 0;
CRect cRect = graphics.getBounds(bean.getPlateName());
CRect plateRect = new CRect(cRect.mLeft,cRect.mTop,cRect.mRight + padding,cRect.mBottom + padding);
boolean isLeft = bean.getxPos()<centerX; //是否在X中轴左侧,在左侧的话绘制时相对分时上的点朝右,右侧时绘制时相对分时上的点朝左
bean.setPointX(isLeft?bean.getxPos():( bean.getxPos() - plateRect.Width())); //调整标签左上角x坐标
int dotY = bean.getDotY();
if(dotY <centerY){
//分时上的点位于Ÿ中轴上方,标签优先绘制在ÿ中轴下方
//判断最佳位置是否与其他标签相交
{
boolean bl = false;
CRect r1 = new CRect(bean.getPointX(),dotY + offsetY,bean.getPointX()+ plateRect.Width(),dotY + offsetY + plateRect.Height());
for(MarketChangeBean labelBean:labelArr){
CRect cR = graphics.getBounds(labelBean.getPlateName());
CRect lastRect = new CRect(cR.mLeft,cR.mTop,cR.mRight + padding,cR.mBottom + 10);
CRect r2 = new CRect(labelBean.getPointX(),labelBean.getPointY(),labelBean.getPointX()+ lastRect.Width(),labelBean.getPointY()+ lastRect.Height());
if(isIntersect(r1,r2)){//表示没有交集
bl = true;
打破;
}
}
if(!bl){//最佳位置与其他标签没相交
bean.setPointY(dotY + offsetY);
bean.setLineY(dotY + offsetY + r1.Height());
labelArr.add(豆); //将已绘制的标签添加到集合当中
继续;
}
}
//最佳位置与其他标签相交,开始计算ÿ
y = maxH;
boolean intersect = false;
做{
y - =(plateRect.Height()+ marginY);
if(y <= 0){
intersect = false;
打破;
}
//判断最佳位置是否与其他标签相交
CRect r1 = new CRect(bean.getPointX(),y,bean.getPointX()+ plateRect.Width(),y + offsetY);
for(MarketChangeBean labelBean:labelArr){
CRect cR = graphics.getBounds(labelBean.getPlateName());
CRect lastRect = new CRect(cR.mLeft,cR.mTop,cR.mRight + padding,cR.mBottom + 10);
CRect r2 = new CRect(labelBean.getPointX(),labelBean.getPointY(),labelBean.getPointX()+ lastRect.Width(),labelBean.getPointY()+ lastRect.Height());
if(isIntersect(r1,r2)){
intersect = true;
打破;
} else {
intersect = false;
}
}
而(相交);
if(y <= 0){
//没位置绘制
y =(int)(Math.random()*(maxH - plateRect.Height()));
}
bean.setPointY(Y);
bean.setLineY(y <centerY?y:y + plateRect.Height());
labelArr.add(豆); //将已绘制的标签添加到集合当中
} else {
//分时上的点位于Ÿ中轴下方,标签优先绘制在ÿ中轴上方
//判断最佳位置是否与其他标签相交
{
boolean bl = false;
CRect r1 = new CRect(bean.getPointX(),dotY - offsetY - plateRect.Height(),bean.getPointX()+ plateRect.Width(),dotY - offsetY);
for(MarketChangeBean labelBean:labelArr){
CRect cR = graphics.getBounds(labelBean.getPlateName());
CRect lastRect = new CRect(cR.mLeft,cR.mTop,cR.mRight + padding,cR.mBottom + 10);
CRect r2 = new CRect(labelBean.getPointX(),labelBean.getPointY(),labelBean.getPointX()+ lastRect.Width(),labelBean.getPointY()+ lastRect.Height());
if(isIntersect(r1,r2)){
bl = true;
打破;
}
}
if(!bl){
//最佳位置与其他标签没相交
bean.setPointY(dotY - offsetY - plateRect.Height());
bean.setLineY(dotY - offsetY - plateRect.Height());
labelArr.add(豆); //将已绘制的标签添加到集合当中
继续;
}
}
//最佳位置与其他标签相交,开始计算ÿ
y = minH;
boolean intersect = false;
做{
y + =(plateRect.Height()+ marginY);
if(y> = maxH - plateRect.Height()){
intersect = false;
打破;
}
CRect r1 = new CRect(bean.getPointX(),y,bean.getPointX()+ plateRect.Width(),y + offsetY);
for(MarketChangeBean labelBean:labelArr){
CRect cR = graphics.getBounds(labelBean.getPlateName());
CRect lastRect = new CRect(cR.mLeft,cR.mTop,cR.mRight + padding,cR.mBottom + 10);
CRect r2 = new CRect(labelBean.getPointX(),labelBean.getPointY(),labelBean.getPointX()+ lastRect.Width(),labelBean.getPointY()+ lastRect.Height());
if(isIntersect(r1,r2)){
intersect = true;
打破;
} else {
intersect = false;
}
}
而(相交);
if(y> = maxH - plateRect.Height()){
//没位置绘制,随机一个ÿ值
y =(int)(Math.random()*(maxH - plateRect.Height()));
}
bean.setPointY(Y);
bean.setLineY(Y);
labelArr.add(豆);
}
}}