经常用QQ的朋友应该知道,QQ头像是圆的。那么正方形,六边形,或者其它异形怎么实现的,其实原理都是一样的。把图片进行渲染,然后利用path指定显示区域即可。今天分享的就是六边形。
正六边形画法
正六边形的边长l就是宽的一半,正六边形的高是 Math.sqrt(3)*l ,然后可以算出正六边形顶部的top值,之后只要依次遍历连接每个点,即可画出正六边形。
float l = (float) (getWidth() / 2); float h = (float) (Math.sqrt(3)*l); float top = (getHeight() - h) / 2 ; mPath.reset(); mPath.moveTo(l/2,top); mPath.lineTo(0,h/2+top); mPath.lineTo(l/2,h+top); mPath.lineTo((float) (l*1.5),h+top); mPath.lineTo(2*l,h/2+top); mPath.lineTo((float) (l*1.5),top); mPath.lineTo(l/2,top); mPath.close();
设置Shader
对于Shader还不了解的人,可以去搜一搜其他博客,讲这个的已经很多了,我就不再讲一遍了。这里我们使用的是BitmapShader,这个类名副其实,它可以把一个Bitmap做为我们的渲染对象,在设置Bitmap的时候把Bitmap初始化BitmapShader,然后设置给Paint。直接上代码了。
// 先把要设置的bitmap设置给一个BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP) ; // 然后给Paint设置shader mPaint.setShader(shader);
使用Shader绘制正六边形
我们重写onDraw方法:
@Override public void onDraw(Canvas canvas) { canvas.drawPath(mPath,mPaint); }
封装到Drawable中
public class HiveDrawable extends Drawable { // 用于记录边界信息的Rect Rect mRect = new Rect(); Paint mPaint; Path mPath ; BitmapShader mShader; Bitmap mBitmap ; public HiveDrawable() { this(null) ; } public HiveDrawable(Bitmap bitmap) { init(); setBitmap(bitmap); } private void init() { initPaint() ; initPath() ; } private void ensurePaint(){ if (mPaint == null) { mPaint = new Paint() ; } } private void ensurePath(){ if (mPath == null) { mPath = new Path() ; } } private void initPaint() { ensurePaint(); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.FILL); mPaint.setStrokeWidth(3f); } public Bitmap getBitmap() { return mBitmap; } // 设置Bitmap的时候初始化shader,并设置给paint public void setBitmap(Bitmap bitmap) { this.mBitmap = bitmap; if (bitmap == null) { mShader =null ; } else { mShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP) ; mPaint.setShader(mShader) ; } } // 初始化好Path要走的路径 private void initPath() { ensurePath(); float l = (float) (mRect.width() / 2); float h = (float) (Math.sqrt(3)*l); float top = (mRect.height() - h) / 2 ; mPath.reset(); mPath.moveTo(l/2,top); mPath.lineTo(0,h/2+top); mPath.lineTo(l/2,h+top); mPath.lineTo((float) (l*1.5),h+top); mPath.lineTo(2*l,h/2+top); mPath.lineTo((float) (l*1.5),top); mPath.lineTo(l/2,top); mPath.close(); } @Override public void draw(Canvas canvas) { canvas.drawPath(mPath,mPaint); } @Override public void setAlpha(int alpha) { if (mPaint != null) { mPaint.setAlpha(alpha); } } @Override public void setColorFilter(ColorFilter colorFilter) { if (mPaint != null) { mPaint.setColorFilter(colorFilter) ; } } @Override public int getOpacity() { return 0 ; } // 设置边界信息 @Override public void setBounds(int left, int top, int right, int bottom) { super.setBounds(left, top, right, bottom); mRect.set(left, top, right, bottom); initPath(); } @Override public int getIntrinsicWidth() { if (mBitmap != null) { return mBitmap.getWidth(); } else { return super.getIntrinsicWidth() ; } } @Override public int getIntrinsicHeight() { if (mBitmap != null) { return mBitmap.getHeight() ; } return super.getIntrinsicHeight(); }
來源:简书
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (0)
站点信息
- 文章2305
- 用户1336
- 访客11455187
每日一句
Talent without working hard is nothing.
没有努力,天份不代表什么。
没有努力,天份不代表什么。
MySQL 数据库优化
This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its de
免ROOT实现模拟点击任意位置
Mobaxterm终端神器
CreateProcessW要注意的细节问题
Autonomous NAT Traversal
【教程】win10 彻底卸载edge浏览器
eclipse工程基于Xposed的一个简单Hook
排名前5的开源在线机器学习
Mac OS最简单及(Karabiner)快捷键设置
发一款C++编写的麻将
VMware NAT端口映射外网访问虚拟机linux
独家发布最新可用My-AutoPost——wordpress 采集器
新会员