Android自定义六边形控件

Android自定义六边形控件

一.效果图
https://github.com/MhuiHugh/Android-Hexagon

点击事件

二.核心算法
平面内一个坐标点是否在多边形内判断,使用射线法判断。从目标点出发引一条射线,看这条射线和多边形所有边的交点数目。如果是奇数个交点,则说明点在多边形内部;如果是偶数个交点,则说明在外部。
示例图

算法图解:
算法图解

参考代码:

int pnpoly(int nvert, float *vertx, float *verty, float testx, float testy)
{
  int i, j, c = 0;
  for (i = 0, j = nvert-1; i < nvert; j = i++) 
  {
    if ( ((verty[i]>testy) != (verty[j]>testy)) &&
     (testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
       c = !c;
  }
  return c;
}

更多参考信息:
http://www.cnblogs.com/luxiaoxun/p/3722358.html
http://www.html-js.com/article/1528
http://www.cppblog.com/w2001/archive/2007/09/06/31694.html

三.知识点
1.控件属性自定义和使用
在values->attrs->declare-styleable中定义属性;在布局中引入(格式xmls:sec=”http://schemas.android.com/apk/res/程序包名”);使用sec:text=”Hello”;在代码中通过AttributeSet获取属性值AttributeSet.getString(R.styleable.HeagonView_text);

2.Paint画笔使用
class继承View后重写onDraw方法,Paint paint=new Paint().setStyle(Style.FILL);
canvas.drawText(“Hello”,x,y,paint);

3.Path路径使用
Path path=new Path(); path.moveTo(x1,y1); path.lineTo(x2,y2); path.close(); canvas.drawPath(path,paint);

4.图片缩放平铺居中
六边形视图显示为正方形,如属性设置图片宽高不相等直接使用图片会被拉伸变形。通过逻辑处理以图片宽高较小值居中裁剪图片。

 /**
     * 按宽/高缩放图片到指定大小并进行裁剪得到中间部分图片
     *
     * @param bitmap 源bitmap
     * @param w      缩放后指定的宽度
     * @param h      缩放后指定的高度
     * @return 缩放后的中间部分图片
     */
    public static Bitmap zoomBitmap(Bitmap bitmap, int w, int h) {
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        float scaleWidht, scaleHeight, x, y;
        Bitmap newbmp;
        Matrix matrix = new Matrix();
        if (width > height) {
            scaleWidht = ((float) h / height);
            scaleHeight = ((float) h / height);
            x = (width - w * height / h) / 2;// 获取bitmap源文件中x做表需要偏移的像数大小
            y = 0;
        } else if (width < height) {
            scaleWidht = ((float) w / width);
            scaleHeight = ((float) w / width);
            x = 0;
            y = (height - h * width / w) / 2;// 获取bitmap源文件中y做表需要偏移的像数大小
        } else {
            scaleWidht = ((float) w / width);
            scaleHeight = ((float) w / width);
            x = 0;
            y = 0;
        }
        matrix.postScale(scaleWidht, scaleHeight);
        try {
            newbmp = Bitmap.createBitmap(bitmap, (int) x, (int) y,
                    (int) (width - x), (int) (height - y), matrix, true);// createBitmap()方法中定义的参数x+width要小于或等于bitmap.getWidth(),y+height要小于或等于bitmap.getHeight()
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return newbmp;
    }

5.动画(ScaleAnimation)

 Animation scaleAnimation = new ScaleAnimation(start, end, start, end,
                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                0.5f);
        scaleAnimation.setDuration(30);
        scaleAnimation.setFillAfter(true);
        this.startAnimation(endAnimation);

6.监听实现

HexagonView.java ->
public interface OnHexagonViewClickListener {
        public void onClick(View view);
    }
public void setOnHexagonClickListener(OnHexagonViewClickListener listener) {
        this.listener = listener;
    }
OnHexagonViewClickListener hexagonListener=new OnHexagonViewClickListener();//实例化
/**
*系统onTouchEvent
*/
public boolean onTouchEvent(MotionEvent event){
   if(!isOn){//未点中六边形
      break;
   }
  switch(event.getAction()){
   case MotionEvent.ACTION_UP:
      if(hexagonListener!=null){
      hexagonListener.click(this);
     }
     break;
  }
}

MainActivity->
public class MainActivity extends Activity implements HexagonView.OnHexagonViewClickListener{
 HexagonView hexagonViewHello;
 public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       hexagonViewHello=(HexagonView)this.findViewById(R.id.hexagonviewhello);
       hexagonViewHello.setOnHexagonClickListener(this);
    }
    /**
     * 事件监听
     */
    public void onClick(View view){
        Log.d(TAG,"onClick()");
        switch (view.getId()){
            case R.id.hexagonviewhello:
                Toast.makeText(this,"Hello",Toast.LENGTH_SHORT).show();
                break;
            }
         }

}

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论 2

打赏作者

大橘为重_

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值