项目需要做一个蜂巢的控件,虽然不是啥难事,但是程序员其实就应该发扬拣现成的,就像没有必要每个人都写一个json解析器一样。除非写的效率不高,或者不太好用。我们可以改装,学习其优点。于是就在CSDN发现一篇文章,然后也转载到本站中,不过那个仅仅是实现绘制多个六边形。我们取其基础随便改装一下,就可以达到自己想要的效果。先看图:
这种定制的7个六边形菜单,并且实现了异形点击事件。上源码:
values\attrs.xml创建该文件
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="HiveLayout"> <attr name="item_length" format="dimension" /> </declare-styleable> </resources>
目的是加一个属性,动态控制单个六边形的连长,也就是大小。接下来是布局源码
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 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"> <com.app.newlight.view.HiveLayout android:id="@+id/id_hive" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" app:item_length="60dp" /> </RelativeLayout>
然后就是单个六边形控件类
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<Integer> mColorList; public HiveLayout(Context context, AttributeSet attrs) { super(context, attrs); HexagonViews = new HexagonView[7]; for (int i = 0; i < HexagonViews.length; i++) { HexagonViews[i] = new HexagonView(context, attrs); HexagonViews[i].setId(i); addView(HexagonViews[i]); } mColorList = new ArrayList<Integer>(); 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 < nCount; 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 << 1; 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 < nCount; 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)); } }
收藏的用户(0) X
正在加载信息~
推荐阅读
站点信息
- 文章2300
- 用户1336
- 访客10865213
每日一句
To be a happy man.
做一个幸福的人。
做一个幸福的人。
新会员