Finally I've came to the solution!!
The padding solution is good for a static map but when you want to do continuance animation on the map like in navigation, the padding causes to un expected movement in turns, especially when the map tilts and zoomed!!
The MapView size solution is the right choice here as it simply push the center of the map.
The problem with that approach is that it also pushes down the zoom control and most important the Google logo which must be visible.
So, you have to explicitly set the the zoom control and Google logo bottom margin back so they will be visible again! This without putting any padding to the map view itself.
Alternatively you can set the controls and the logo position to different corners if it's ok for your need, I've decided just to set their margins.
Here is my code:
final ViewTreeObserver observer = mapView.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mainParentLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
int parentHeight = ((ViewGroup)mapView.getParent()).getHeight() - toolbar.getHeight();
int mapHeight = parentHeight + parentHeight/2;
mapView.getLayoutParams().height = mapHeight;
int margin = mapHeight - parentHeight + 2*((int)(getResources().getDimension(R.dimen.small_image) + getResources().getDimension(R.dimen.small_pargin)));
Log.i(TAG, "onGlobalLayout: parent height: " + parentHeight + ", map new height: " + mapHeight + ", margin: " + margin);
setMapControlsMargin(margin);
}
});
This code, waits for the map view to be shown, then it calculate the map parent view height (in my case a ConstraintLayout) then it set the map height to be parentHeight * 1.5. This will push the camera center down!
Then, set the margin the Google logo and zoom controls.
private void setMapControlsMargin(final int margin){
try {
//Find the Zoom controls parent
final ViewGroup parent = (ViewGroup) mapView.findViewWithTag("GoogleMapMyLocationButton").getParent();
//Find the Google logo parent view group
final ViewGroup googleLogo = (ViewGroup) mapView.findViewWithTag("GoogleWatermark").getParent();
Log.i(TAG, "setMapControlsMargin: found Google logo " + (googleLogo != null));
//Set the margin for the Google logo
if (googleLogo != null) {
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) googleLogo.getLayoutParams();
layoutParams.bottomMargin = margin;
}
parent.post(() -> {
try {
View zoomControls = parent.getChildAt(2); //Zoom controls
ViewGroup.LayoutParams layoutParams1 = zoomControls.getLayoutParams();
//Read the zoom controls original margin, this will be added to the offset margin
int origBotMargin = ((RelativeLayout.LayoutParams) layoutParams1).bottomMargin;
int origRightMargin = ((RelativeLayout.LayoutParams) layoutParams1).rightMargin;
// create layoutParams, giving it our wanted width and height(important, by default the width is "match parent")
RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(zoomControls.getWidth(),zoomControls.getHeight());
// position on bottom right
rlp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
rlp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
//set the new margin
rlp.setMargins(0, 0, origRightMargin, origBotMargin + margin);
zoomControls.setLayoutParams(rlp);
} catch (Exception ex) {
ex.printStackTrace();
}
});
} catch (Exception ex) {
ex.printStackTrace();
}
}
I was helped this post to move the Google logo.