项目需要做一个蜂巢的控件,虽然不是啥难事,但是程序员其实就应该发扬拣现成的,就像没有必要每个人都写一个json解析器一样。除非写的效率不高,或者不太好用。我们可以改装,学习其优点。于是就在CSDN发现一篇文章,然后也转载到本站中,不过那个仅仅是实现绘制多个六边形。我们取其基础随便改装一下,就可以达到自己想要的效果。先看图:
这种定制的7个六边形菜单,并且实现了异形点击事件。上源码:
values\attrs.xml创建该文件<?xml version="1.0" encoding="utf-8"?>
目的是加一个属性,动态控制单个六边形的连长,也就是大小。接下来是布局源码<?xml version="1.0" encoding="utf-8"?>
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.app.MainActivity">
android:id="@+id/id_hive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
app:item_length="60dp" />
然后就是单个六边形控件类public class HexagonView extends View {
private float mLength;
private float mHeight;
private Paint mPaint;
private Path mPath;
private OnClickListener listener;
//点击事件
private RectF r;
private Region re;
public HexagonView(Context context, AttributeSet attrs) {
super(context, attrs);
re = new Region();
r = new RectF();
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPath = new Path();
TypedArray typedArray = getResources().obtainAttributes(attrs,
R.styleable.HiveLayout);
mLength = typedArray.getDimension(0, 60);
typedArray.recycle();
mHeight = (float) (Math.sqrt(3) * mLength);
}
public void setColor(int color) {
mPaint.setColor(color);
}
/**
* 获取边长
*
* @return
*/
public float getmLength() {
return mLength;
}
public void setmLength(float mLength) {
this.mLength = mLength;
mHeight = (float) (Math.sqrt(3) * mLength);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (widthMode == MeasureSpec.AT_MOST) {
widthSize = (int) (mLength * 2f);
} else {
// throw new IllegalStateException("only support wrap_content");
}
if (heightMode == MeasureSpec.AT_MOST) {
heightSize = (int) (Math.sqrt(3) * mLength);
} else {
// throw new IllegalStateException("only support wrap_content");
}
setMeasuredDimension(widthSize, heightSize);
}
//根据左上角一点 绘制整个正六边形
private void getPath(float height, float x, float y) {
mPath.moveTo(x, y);
//逆时针顺序绘制六边形
mPath.lineTo(x - mLength / 2, height / 2 + y);
mPath.lineTo(x, height + y);
mPath.lineTo(x + mLength, height + y);
mPath.lineTo((float) (x + 1.5 * mLength), height / 2 + y);
mPath.lineTo(x + mLength, y);
mPath.lineTo(x, y);
mPath.close();
//计算控制点的边界
mPath.computeBounds(r, true);
//设置区域路径和剪辑描述的区域
re.setPath(mPath, new Region((int) r.left, (int) r.top, (int) r.right, (int) r.bottom));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//正六边形的高
float x = mLength / 2f;
getPath(mHeight, x, 0);
canvas.drawPath(mPath, mPaint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN && listener != null && inPath(event.getX(), event.getY()))
listener.onClick(this);
return super.onTouchEvent(event);
}
public boolean inPath(float x, float y) {
return re.contains((int) x, (int) y);
}
public void setOnClickListener(OnClickListener listener) {
this.listener = listener;
}
public interface OnClickListener {
public void onClick(View view);
}
}
定制的布局代码public class HiveLayout extends ViewGroup {
private HexagonView[] HexagonViews;
private List mColorList;
public HiveLayout(Context context, AttributeSet attrs) {
super(context, attrs);
HexagonViews = new HexagonView[7];
for (int i = 0; i
HexagonViews[i] = new HexagonView(context, attrs);
HexagonViews[i].setId(i);
addView(HexagonViews[i]);
}
mColorList = new ArrayList();
mColorList.add(Color.parseColor("#33B5E5"));
mColorList.add(Color.parseColor("#AA66CC"));
mColorList.add(Color.parseColor("#99CC00"));
mColorList.add(Color.parseColor("#FFBB33"));
mColorList.add(Color.parseColor("#FF4444"));
}
public void setOnClickListener(HexagonView.OnClickListener listener) {
for (HexagonView h : HexagonViews) {
if (h == null)
continue;
h.setOnClickListener(listener);
}
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
}
@Override
protected LayoutParams generateDefaultLayoutParams() {
return new MarginLayoutParams(-2, -2);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int cWidth = 0;
int cHeight = 0;
int nCount = getChildCount();
for (int i = 0; i
HexagonView childView = (HexagonView) getChildAt(i);
childView.setColor(mColorList.get(i % mColorList.size()));
cWidth = childView.getMeasuredWidth();
cHeight = childView.getMeasuredHeight();
int cl = 0, ct = 0, cr = 0, cb = 0;
switch (i) {
case 0:
cl = (int) (1.5f * childView.getmLength());
ct = 0;
break;
case 1:
cl = 0;
ct = cHeight >> 1;
break;
case 2:
cl = (int) (3f * childView.getmLength());
ct = cHeight >> 1;
break;
case 3:
cl = (int) (1.5f * childView.getmLength());
ct = cHeight;
break;
case 4:
cl = 0;
ct = (int) (cHeight * 1.5f);
break;
case 5:
cl = (int) (3f * childView.getmLength());
ct = (int) (cHeight * 1.5f);
break;
case 6:
cl = (int) (1.5f * childView.getmLength());
ct = cHeight <
break;
}
cr = cl + cWidth;
cb = cHeight + ct;
childView.layout(cl, ct, cr, cb);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
measureChildren(widthMeasureSpec, heightMeasureSpec);
int nCount = getChildCount();
for (int i = 0; i
//求出大小即可
HexagonView childView = (HexagonView) getChildAt(i);
widthSize = (int) (childView.getmLength() * 5f);
heightSize = childView.getMeasuredHeight() * 3;
break;
}
setMeasuredDimension(widthSize, heightSize);
}
}
最后就是Activity活动视窗类代码public class MainActivity extends LActivity implements HexagonView.OnClickListener {
private HiveLayout layout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layout = findViewById(R.id.id_hive);
layout.setOnClickListener(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
System.exit(0);
}
@Override
public void onClick(View view) {
int id = view.getId();
MLog.logInfo(String.format("六边形:%d", id));
}
}