-1

I would like to show the direction images on all sides of the screen. E.g. if the target's location is the right side of user's location and is outside of the visible map area, then I want to add a direction image as shown on the picture below (The Green annotation is user's location, red one is the direction for the target, which is out of bounds of the screen):

I found a solution for IOS here: Direction of target annotation when outside of visible area But unable to find solution in android yet.

Community
  • 1
  • 1
Ahsanwarsi
  • 1,013
  • 9
  • 18

1 Answers1

3

Finally i found the solution:

//Add at class level
    private static final int NORTH = 1;
    private static final int SOUTH = 2;
    private static final int EAST = 3;
    private static final int WEST = 4;
    private ImageView imgEast;
    private ImageView imgWest;
    private ImageView imgNorth;
    private ImageView imgSouth;

    private LatLng source;
    private LatLng target;

//In onCreate or somewhere else
    imgEast = (ImageView) findViewById(R.id.east);
    imgWest = (ImageView) findViewById(R.id.west);
    imgNorth = (ImageView) findViewById(R.id.north);
    imgSouth = (ImageView) findViewById(R.id.south);

    source = new LatLng(31.499851, 74.317489);
    target = new LatLng(33.736189, 73.096848);

//Add after populating map
            googleMap.setOnCameraChangeListener(new OnCameraChangeListener() {
                @Override
                public void onCameraChange(CameraPosition position) {
                    if(isLocationVisible(source) && !isLocationVisible(target)){

                        double bearing = calculateBearing(source, target);
                        showCardinalPointDirection(bearing);
                    }else{
                        hideCardinalPointers();
                    }
                }
            });

    public boolean isLocationVisible(LatLng latLng){
        LatLngBounds curScreen = googleMap.getProjection()
                .getVisibleRegion().latLngBounds;
        if(curScreen.contains(latLng)){
            return true;
        }else{
            return false;
        }
    }

    private double calculateBearing(LatLng source, LatLng target){
        double lat1 = DegreesToRadians(source.latitude);
        double lon1 = DegreesToRadians(source.longitude);

        double lat2 = DegreesToRadians(target.latitude);
        double lon2 = DegreesToRadians(target.longitude);

        double dLon = lon2 - lon1;

        double y = Math.sin(dLon) * Math.cos(lat2);
        double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon);
        double radiansBearing = Math.atan2(y, x);

        if(radiansBearing < 0.0)
            radiansBearing += 2*Math.PI;

        return RadiansToDegrees(radiansBearing);
    }

    private void showCardinalPointDirection(double bearing){
        int direction = cardinalPointWithBearing(bearing);
        View activeDirection = null;
        switch(direction){
        case EAST:
            activeDirection = this.imgEast;
            break;
        case WEST:
            activeDirection = this.imgWest;
            break;
        case SOUTH:
            activeDirection = this.imgSouth;
            break;
        case NORTH:
            activeDirection = this.imgNorth;
            break;
        }

        //Hide all pointers
        hideCardinalPointers();

        //Visible only active direction pointer
        activeDirection.setVisibility(View.VISIBLE);

        //Set rotation to show direction
        activeDirection.setRotation((float)bearing);
    }

    private int cardinalPointWithBearing(double bearing){
        if (bearing > 45.0 && bearing <= 135.0) {
            return EAST;
        } else if (bearing > 135.0 && bearing <= 225.0) {
            return SOUTH;
        } else if (bearing > 225.0 && bearing <= 315.0) {
            return WEST;
        } else {
            return NORTH;
        }
    }

    double DegreesToRadians(double degrees) {
        return degrees * Math.PI / 180.0;
    };

    double RadiansToDegrees(double radians) {
        return radians * 180.0/Math.PI;
    };

    private void hideCardinalPointers(){
        imgEast.setVisibility(View.INVISIBLE);
        imgWest.setVisibility(View.INVISIBLE);
        imgSouth.setVisibility(View.INVISIBLE);
        imgNorth.setVisibility(View.INVISIBLE);
    }
Ahsanwarsi
  • 1,013
  • 9
  • 18