Search code examples
javaandroidandroid-studioscreen-orientationscreen-size

Connecting two ImageViews with each other with a line correctly on different screen-sizes and screen-orientations


I am looking for a way to connect two ImageViews with a line. The position of the ImageViews on the screen always differs. I want to draw these lines as reactions to a click of the user, so I need a programmatic solution. It also needs to work with different sizes of screens (mobile, tablet) and screen orientations (portrait, landscape).

My attempt so far has been to create a custom view and use Canvas to connect these two points:

private Paint paint = new Paint();
private Point pointA, pointB;
 @Override
    protected void onDraw(Canvas canvas) {
        paint.setColor(Color.BLACK);
        paint.setStrokeWidth(6);
        canvas.drawLine(pointA.x, pointA.y, pointB.x, pointB.y, paint);
        super.onDraw(canvas);
    }
    public void draw() {
        invalidate();
        requestLayout();
    }

I get the position of the ImageViews with viewA.getLocationOnScreen(positionA) and then adjust this to select the center of the ImageView by adding (viewA.getWidth() / 2) and (viewA.getHeight() / 2). Unfortunately, with different screen sizes and screen orientations, it happens again and again that the points are not connected correctly, i.e. there is an offset. I have tried in various ways to correct the offset (e.g. including the status bar), unfortunately it never works for all screen sizes and orientations. I've also tried to react specifically for different screen sizes and orientations, but then it doesn't work even for almost the same screen sizes (e.g. it works for a Samsung Galaxy S10, but not for a Nokia 7.2). The following is just a sample code, I have tried it in very many different ways and did not get the desired result:

 private int topOffset() {
        View globalView = findViewById(R.id.constraintLayoutStartBildschirm);
        DisplayMetrics dm = new DisplayMetrics();
        this.getWindowManager().getDefaultDisplay().getMetrics(dm);
        topOff = dm.heightPixels - globalView.getMeasuredHeight();
        return topOff;
 }
 private int leftOffset() {
        View globalView = findViewById(R.id.constraintLayoutStartBildschirm);
        DisplayMetrics dm = new DisplayMetrics();
        this.getWindowManager().getDefaultDisplay().getMetrics(dm);
        leftOff = dm.widthPixels - globalView.getMeasuredWidth();
        return leftOff;
 }
private void zeichneStriche(ImageView viewA, ImageView viewB, Linien linie) {
        int[] positionA = new int[2];
        int[] positionB = new int[2];
        viewA.getLocationOnScreen(positionA);
        viewB.getLocationOnScreen(positionB);
        int xCenterA = positionA[0] + (int) (viewA.getWidth() / 1.5 ) - leftOffset();
        int xCenterB = positionB[0] + (int) (viewA.getWidth() / 1.5 ) - leftOffset();
        int yBottemA = positionA[1] + (int) (viewA.getWidth() / 1.8) - topOffset();
        int yBottemB = positionB[1] + (int) (viewB.getWidth() / 1.8) - topOffset();

        if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
            xCenterA = positionA[0] + (int) (viewA.getWidth() / 2 ) - leftOffset() - 20;
            xCenterB = positionB[0] + (int) (viewB.getWidth() / 2 ) - leftOffset() - 20;
            yBottemA = positionA[1]  + viewA.getHeight() / 2 - topOffset();
            yBottemB = positionB[1]  + viewB.getHeight() / 2 - topOffset();
        }

        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);

        float yInches= metrics.heightPixels/metrics.ydpi;
        float xInches= metrics.widthPixels/metrics.xdpi;
        double diagonalInches = Math.sqrt(xInches*xInches + yInches*yInches);

        if((getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) && diagonalInches>=7.5) {
            xCenterA = positionA[0] + (int) (viewA.getWidth() / 2 ) - leftOffset() + 50;
            xCenterB = positionB[0] + (int) (viewB.getWidth() / 2 ) - leftOffset() + 50;
            yBottemA = positionA[1]  + viewA.getHeight() / 2 - topOffset() +5;
            yBottemB = positionB[1]  + viewB.getHeight() / 2 - topOffset() + 5;
        }
        Point anfang = new Point(xCenterA, yBottemA);
        Point ende = new Point(xCenterB, yBottemB);
        linie.setPointA(anfang);
        linie.setPointB(ende);
        linie.draw();
    }

Is there a solution where I can be sure that it will at least work for most screen sizes and orientations? Thanks in advance


Solution

  • Use View.getGlobalVisibleRect (Rect r) to resolve the issue. Good one @Nulldroid