簡體   English   中英

具有可點擊區域的Android圖片

[英]Android image with clickable areas

我需要一個如何在Android下實現以下功能的建議:

  • 我需要一個代表圖形(來自離散數學)的圖像,帶有頂點和邊緣,我可以點擊每個頂點或邊緣並觸發不同的動作。

請告訴我如何實現這一點(可能使用imagebuttons )或其他方法來表示此功能。

我很無聊,所以我編寫了這個粗略的例子......它假定了點之間的直邊。

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;
            }
        }       
    }
}

我可以想象如何使用SurfaceView執行此操作:

  • 創建一個Vertex類,其中包含一個x,y坐標,表示繪制頂點的位置。 如果您的頂點是圓的png圖像,則圖像的左上角x,y坐標存儲在Vertex類中。
  • 將所有頂點放在List ,並迭代並繪制每個頂點。
  • 邊緣更復雜,因為它們可能縱橫交錯或彎曲。
    • 假設它們是直線,那么您可以使用包含起始x,y和結束x,y坐標的Edge類。
    • 您可以迭代Edge of List並相應地繪制線條

為了檢測用戶何時單擊它們,您應該覆蓋onTouch方法並檢查event.rawX()event.rawY()值,以查看它們是否與Vertex或Edge類匹配。

  • 對於Vertex類,您可以檢查x <= event.rawX <= x + image_widthy <= event.rawY <= y + image_height

  • 對於Edge ,您可以檢查是否在由Edge類中存儲的兩組坐標形成的行中找到event.rawX, event.rawY坐標。

我已經使用類似的方法在游戲中繪制一組節點。 我不太確定如何做到這一點 - 我概述的方法只有在它們是直的並且不會縱橫交錯時才有效。

我確信使用openGL有更好的方法,但我之前沒有使用過openGL。

希望你能從中得到一些想法。

我認為你最好使用SurfaceView:

http://developer.android.com/reference/android/view/SurfaceView.html

並將onTouchEvent()作為整體處理表面,並將其映射到圖像中的基礎實體。 如果你正在計算繪圖,那么你應該很容易創建一個可點擊區域的地圖,並抓住觸摸事件的X和Y來確定它是否與圖像中的元素相對應。

如果您確實擁有一個圖像,例如已經處理過的PNG,您需要某種方式來攜帶觸摸事件區域。 取決於圖像的來源。

根據android的幫助,“繪制到視圖,當你想繪制不需要動態改變的簡單圖形並且不是性能密集型游戲的一部分時,它是你的最佳選擇。” 例如,這是制作蛇或國際象棋比賽的正確方法。 所以我沒有看到建議使用SurfaceView的一點,它只會使事情過於復雜。

對於可點擊區域,您可以覆蓋公共布爾值onTouchEvent(MotionEvent事件) ,您可以在其中管理點擊的x和y坐標以識別單擊的區域。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM