在Android中绘制箭头头部

6
我正在尝试绘制箭头以指向图像中的对象。我已经能够编写绘制线条的代码,但似乎找不到绘制箭头的方法。我编写的绘制可拖动线条的代码如下。我需要在 ACTION_UP 事件上绘制箭头,以指向线条所指向的方向。
if(event.getAction() ==MotionEvent.ACTION_DOWN) {         
     if (count==1){ 
          x1 = event.getX();
          y1 = event.getY();
          System.out.println(count+"count of value a;skd");
          Toast.makeText(getApplicationContext(), ""+(radius+count), Toast.LENGTH_LONG).show();

          Log.i(TAG, "coordinate x1 : "+String.valueOf(x1)+" y1 : "+String.valueOf(y1));
     }
}
else if(event.getAction() ==MotionEvent.ACTION_MOVE){

     imageView.setImageBitmap(bmp2);
     x2 = event.getX();
     y2 = event.getY();
     posX=(float)(x1+x2)/2;
     posY=(float)(y1+y2)/2;
     radius=(float) Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2))/2;
     onDraw();
     Toast.makeText(getApplicationContext(), ""+radius, Toast.LENGTH_LONG).show();
}

大家好,如果还需要帮助。以下是我最终的解决方法: 将30.0转换为浮点数:float h = (float) 30.0;

    float phi = (float) Math.atan2(y2 - y1, x2 - x1); 
    float angle1 = (float) (phi - Math.PI / 6); 
    float angle2 = (float) (phi + Math.PI / 6);

    float x3 = (float) (x2 - h * Math.cos(angle1));
    float x4 = (float) (x2 - h * Math.cos(angle2));
    float y3 = (float) (y2 -  h * Math.sin(angle1));
    float y4 = (float) (y2 -  h * Math.sin(angle2));
   c.drawLine(x1, y1,x2,y2 ,pnt);
   c.drawLine(x2, y2,x3,y3 ,pnt);
    c.drawLine(x2, y2,x4,y4 ,pnt);

我得到了来自stackoverflow的被接受答案和iOS部分的帮助。


嗨@user2586488,当您触发ACTION_UP事件时,可以附加图像而不是绘制箭头。 - Deepika Lalra
是的,但图像的方向应与线的方向相匹配。我不能将同一图像用于指向上方和指向下方的线等。 - user2586488
是的...你可以拥有一组图像,这样你就可以根据象限设置方向。 - Deepika Lalra
嗨,我认为这不会起作用,因为一条线可能指向无限的位置,我无法为所有可能性存储图像。 - user2586488
也许这可以帮助你。 http://stackoverflow.com/questions/15393206/draw-a-curve-line-with-arrow-in-android-canvas?rq=1 - Deepika Lalra
谢谢你的帮助,太棒了! - bebosh
3个回答

5
我会这样做:找到两点(起点和终点)之间的连线斜率,斜率为(dy/dx),这将是箭头的好起点。假设您希望箭头底部垂直于箭头线,要找到基础斜率,您需要找到线斜率的相反倒数。例如,假设您的线的斜率为2,则三角形底边的斜率为(-1/2),因为您执行(1/(oldslope))并乘以-1。我不太了解Android,但如果我记得正确,您将在Java中使用drawPolygon方法,并且必须指定4个点(3个唯一的点和一个与第一个相同以关闭它)。给定箭头顶部底边的斜率,我们可以获得前两个点和最后一个点。在开始绘制所需箭头尺寸之前,您应该知道,在这种情况下,b将是您基线的长度。如果您取ϴ=arctan(dy/dx),那么它将给出x轴和您基线之间的角度。有了这个ϴ值,您可以进行ydif = b*sin(ϴ)来获取箭头两个底角之间的y值差异。用xdif = b*cos(ϴ)做同样的事情,可以得到两个基本点之间的x值差异。如果用户绘制的线的最终点的位置是,例如(x1, y1),则三角形底部的位置将是(x1-(xdif/2), y1-(ydif/2))和(x1+(xdif/2), y1+(ydif/2))。这两个点p1和p2是drawPolygon方法中的第一、第二和第四个点。要找到第三个点,我们需要找到原始线的角度,通过使用原始dy/dx做ϴ=arctan(dy/dx)来实现。在实际计算点之前,您首先必须知道箭头尖距离线的末端有多远,我将使用变量h和h = 10。为了获得坐标(x,y),假设线尖的坐标为(x1,y1),您将执行(x1+hcosϴ,y1+hsinϴ)。将其用作drawPolygon()中的第三个值,您应该完成了。抱歉如果我在最后有些匆忙,我有点累了,如果需要帮助,请留言。

非常感谢朋友。这看起来很棒,应该有效。我没有足够的点数来赞同这个答案。 - user2586488
没问题。如果需要帮助,请私信我。 - JPeroutek

1
如果您可以在输入事件中绘制一条线,那么您还可以在其末端绘制一个三角形表示方向。
在另一个项目中,每当触摸网格上的磁点时,我都会绘制一个正方形(如您可以在此处看到here)。很抱歉,我现在无法提供任何示例代码。但是,如果这对您是一个合适的方法,我可能稍后会发布它。

嗨,谢谢回复。这种方法对我可能有效。你能告诉我如何给正方形指定方向,或者如何给三角形指定方向吗? - user2586488
在这种情况下,我没有给正方形任何方向(如您在视频中所看到的)。一种通用的方法是:
  • 记住您开始触摸的点
  • 计算起始点和当前(拖动)位置之间的角度
  • 通过该角度旋转您的三角形
- Father Stack
如何给一个三角形指定角度? - user2586488

1

这是一段很棒的代码,不是我写的。原本是Java Graphics2D代码,我把它转换成了Canvas代码。所有功劳归原作者所有。

private void drawArrowHead(Canvas canvas, Point tip, Point tail)
{
    double dy = tip.y - tail.y;
    double dx = tip.x - tail.x;
    double theta = Math.atan2(dy, dx);
    int tempX = tip.x ,tempY = tip.y;
    //make arrow touch the circle
    if(tip.x>tail.x && tip.y==tail.y)
    {
        tempX = (tip.x-10);
    }
    else if(tip.x<tail.x && tip.y==tail.y)
    {
        tempX = (tip.x+10);
    }
    else if(tip.y>tail.y && tip.x==tail.x)
    {
        tempY = (tip.y-10);
    }
    else if(tip.y<tail.y && tip.x==tail.x)
    {
        tempY = (tip.y+10);
    }
    else if(tip.x>tail.x || tip.x<tail.x)
    {
        int rCosTheta = (int) ((10)*Math.cos(theta)) ;
        int xx = tip.x - rCosTheta;
        int yy = (int) ((xx-tip.x)*(dy/dx) + tip.y);
        tempX = xx;
        tempY = yy;
    }


    double x, y, rho = theta + phi;
    for(int j = 0; j < 2; j++)
    {
        x = tempX - arrowLength * Math.cos(rho);
        y = tempY - arrowLength  * Math.sin(rho);

        canvas.drawLine(tempX,tempY,(int)x,(int)y,this.paint);
        rho = theta - phi;
    }
}

只需调用此函数,即可在线段两侧绘制箭头!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接