具有可点击区域的Android图像

具有可点击区域的Android图像,android,Android,我需要一个如何在Android下实现以下功能的建议: 我需要一个图像,它代表一个类似于图形(来自离散数学)的东西,带有顶点和边,在这里我可以单击每个顶点或边,并触发不同的动作 请告诉我如何实现此功能(可能使用imagebuttons)或其他表示此功能的方法。我可以想象如何使用SurfaceView来实现此功能: 创建一个Vertex类,其中包括一个x,y坐标,表示绘制顶点的位置。如果顶点是圆的png图像,则图像的左上角x、y坐标存储在顶点类中 在列表中列出所有垂直点,然后迭代并绘制每个顶点

我需要一个如何在Android下实现以下功能的建议:

  • 我需要一个图像,它代表一个类似于图形(来自离散数学)的东西,带有顶点和边,在这里我可以单击每个顶点或边,并触发不同的动作

请告诉我如何实现此功能(可能使用
imagebuttons
)或其他表示此功能的方法。

我可以想象如何使用
SurfaceView来实现此功能:

  • 创建一个
    Vertex
    类,其中包括一个x,y坐标,表示绘制顶点的位置。如果顶点是圆的png图像,则图像的左上角x、y坐标存储在
    顶点
    类中
  • 列表中列出所有垂直点,然后迭代并绘制每个顶点
  • 边缘更加复杂,因为它们可能交叉或弯曲。
    • 假设它们是直线,则可以有一个
      Edge
      类,该类包含起始x,y和结束x,y坐标
    • 您可以遍历
      边的
      列表
      ,并相应地绘制线条
为了检测用户何时单击它们,您应该覆盖
onTouch
方法,并检查
event.rawX()
event.rawY()
值,查看它们是否与顶点或边类匹配


  • 对于
    Vertex
    类,您可以检查
    x我认为您最好使用SurfaceView:

    以及为曲面整体处理onTouchEvent(),并将其映射到图像中的底层实体。如果您正在计算绘图,那么边走边绘制图形也应该很容易创建可点击区域的地图,并抓取触摸事件的X和Y,以确定它是否对应于图像中的元素


    如果你真的有一个图像,例如一个已经处理过的PNG,你需要一些方法来在触摸事件区域中进行处理。取决于图像的来源。

    我很无聊,所以我编写了这个粗糙的示例。。。 它假定点之间有直边

    public class App extends Activity
    {
        PlotView plot;
        @Override
        public void onCreate(Bundle sis)
        {
            super.onCreate(sis);
            plot = new PlotView(this);
            setContentView(plot);
        }
    
        public class PlotView extends View
        {
            Paint paint1 = new Paint();
            Paint paint2 = new Paint();
            Point[] points = new Point[10];
    
            public PlotView(Context context)
            {
                super(context);
                paint1.setColor(Color.RED);
                paint2.setColor(Color.BLUE);
                for (int i = 0; i < points.length; i++)
                {
                    points[i] = new Point();
                    points[i].x = (float) (Math.random() * 320);
                    points[i].y = (float) (Math.random() * 480);
                }
                Arrays.sort(points);
            }
    
            @Override
            protected void onDraw(Canvas canvas)
            {
                canvas.drawColor(Color.WHITE);
                for (int i = 0; i < points.length; i++)
                {
                    if (i < points.length - 1)
                    {
                        canvas.drawLine(points[i].x, points[i].y, points[i + 1].x, points[i + 1].y, paint2);
                    }
                    canvas.drawCircle(points[i].x, points[i].y, 5, paint1);             
                }
                super.onDraw(canvas);
            }
    
            @Override
            public boolean onTouchEvent(MotionEvent event)
            {
                switch(event.getAction())
                {
                    case MotionEvent.ACTION_DOWN:
                    {
                        float x = event.getX();
                        float y = event.getY();
    
                        int hitPoint = -1;
                        int closestLeft = -1;
                        int closestRight = -1;
    
                        for (int i = 0; i < points.length; i++)
                        {
                            float dx = x - points[i].x;
                            float dy = y - points[i].y;
    
                            if(i < points.length - 1)
                            {
                                if(points[i].x < x && x < points[i + 1].x)
                                {
                                    closestLeft = i;
                                    closestRight = i + 1;
                                }
                            }
    
                            if (Math.abs(dx) <= 16.0f && Math.abs(dy) <= 16.0f)
                            {
                                hitPoint = i;
                                break;
                            }
                        }
                        if (hitPoint != -1)
                        {
                            Toast.makeText(getContext(), "Hit Point: " + hitPoint, Toast.LENGTH_SHORT).show();                      
                        }
                        else                        
                        if(closestLeft != -1 && closestRight != -1)
                        {
                            float dx = points[closestLeft].x - points[closestRight].x;
                            float dy = points[closestLeft].y - points[closestRight].y;
    
                            final float u = ((x - points[closestLeft].x) * dx + (y - points[closestLeft].y) * dy) / (dx * dx + dy * dy);
    
                            float px = points[closestLeft].x + u * dx;
                            float py = points[closestLeft].y + u * dy;
    
                            if (Math.abs(x - px) <= 16.0f && Math.abs(y - py) <= 16.0f)
                            {
                                Toast.makeText(getContext(), "Hit Line Between: " + closestLeft + " & " + closestRight, Toast.LENGTH_SHORT).show();
                            }
                        }                   
                    }
                }
                return super.onTouchEvent(event);
            }
    
            public class Point implements Comparable<Point>
            {
                float x;
                float y;
                @Override
                public int compareTo(Point other)
                {
                    if (x < other.x) return -1;
                    if (x > other.x) return 1;
                    return 0;
                }
            }       
        }
    }
    
    公共类应用程序扩展活动
    {
    绘图视图绘图;
    @凌驾
    创建时的公共void(Bundle sis)
    {
    super.onCreate(sis);
    绘图=新的绘图视图(此);
    setContentView(绘图);
    }
    公共类PlotView扩展视图
    {
    油漆油漆1=新油漆();
    油漆油漆2=新油漆();
    点[]点=新点[10];
    公共绘图视图(上下文)
    {
    超级(上下文);
    油漆1.setColor(颜色为红色);
    油漆2.setColor(颜色:蓝色);
    对于(int i=0;iif(Math.abs(dx)根据android帮助,“当您想要绘制不需要动态更改且不属于性能密集型游戏的简单图形时,绘制到视图是您的最佳选择。”例如,在制作蛇或象棋游戏时,这是正确的方法。因此,我不认为建议使用SurfaceView进行此操作有任何意义,它只会使事情变得过于复杂


    对于可点击区域,您可以覆盖公共布尔onTouchEvent(MotionEvent事件),在这里您可以管理点击的x和y坐标,以识别点击区域。

    非常感谢示例代码。我将在本周末尝试,并将其设置为“接受答案”。我实际上并没有按照你的建议使用它,但看看它是否符合你的需要。我所说的“图形”是指离散数学。我需要一张线和结的图像,所有线和结都可以点击。可能是@lukle的重复,2011年提出的问题怎么可能是2013年提出的问题的重复?