Reputation: 605
I'm trying to display a custom button on a googlemap.
<Button
android:id="@+id/button_backHome"
android:layout_alignParentRight="true"
android:layout_marginTop="50dp"
android:layout_marginRight="11.5dp"
android:layout_height="39dp"
android:layout_width="39dp"
android:background="@drawable/custom_button"
/>
This displays the button directly below googlemap's Set Camera to Current location button in the top right of the screen, but obviously only on my test device. On other devices these settings don't align the button correctly.
XXHDPI (galaxy S4)
XHDPI (Nexus 10)
What would be a good solution, other then making all the buttons myself? Could I inherit the margins from the google button without knowing the style's name?
I'm pretty much at a loss here, and any help would be Much apreciated.
Thanks in advance!
Upvotes: 4
Views: 1150
Reputation: 13343
Parent Layout for Google Maps map is RelativeLayout
so best approach for custom button alignment with default Google Maps control button (for all screens) is to put that custom button into same layout as default Google Maps control button. Assume our activity with Google Maps map has layout like:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="<YOUR_PACKAGE>.MainActivity">
<fragment
android:id="@+id/map_fragment"
android:name="com.google.android.gms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<ImageView
android:id="@+id/custom_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:visibility="gone"
android:src="@drawable/ic_home_target"/>
</RelativeLayout>
As custom button View is better to use ImageView
, because the default buttons layouts has 9 patches padding in them (details here), or it's necessary to set additional padding to default Google Maps control button. Now it belongs to activity layout. So in onMapReady(GoogleMap googleMap)
we should:
1) get parent View for default Google Maps control button;
2) remove custom button view from root activity layout;
3) add custom button view to parent View for default Google Maps control button (defined in p.1);
4) set alignment for custom button view relative to default Google Maps control button.
With Source code like this:
...
private GoogleMap mGoogleMap;
private MapFragment mMapFragment;
private ImageView mCustomButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCustomButton = (ImageView) findViewById(R.id.custom_button);
mMapFragment = (MapFragment) getFragmentManager()
.findFragmentById(R.id.map_fragment);
mMapFragment.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
// don't forget to allow LOCATION permission
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int locationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
if (locationPermission == PackageManager.PERMISSION_GRANTED) {
setConrolsPositions();
}
} else {
setConrolsPositions();
}
}
void setConrolsPositions() {
try {
mGoogleMap.setMyLocationEnabled(true);
mGoogleMap.getUiSettings().setMyLocationButtonEnabled(true);
// get parent view for default Google Maps control button
final ViewGroup parent = (ViewGroup) mMapFragment.getView().findViewWithTag("GoogleMapMyLocationButton").getParent();
parent.post(new Runnable() {
@Override
public void run() {
try {
// get view for default Google Maps control button
View defaultButton = mMapFragment.getView().findViewWithTag("GoogleMapMyLocationButton");
// remove custom button view from activity root layout
ViewGroup customButtonParent = (ViewGroup) mCustomButton.getParent();
customButtonParent.removeView(mCustomButton);
// add custom button view to Google Maps control button parent
ViewGroup defaultButtonParent = (ViewGroup) defaultButton.getParent();
defaultButtonParent.addView(mCustomButton);
// create layout with same size as default Google Maps control button
RelativeLayout.LayoutParams customButtonLayoutParams = new RelativeLayout.LayoutParams(defaultButton.getHeight(), defaultButton.getHeight());
// align custom button view layout relative to defaultButton
customButtonLayoutParams.addRule(RelativeLayout.ALIGN_LEFT, defaultButton.getId());
customButtonLayoutParams.addRule(RelativeLayout.BELOW, defaultButton.getId());
// add other settings (optional)
mCustomButton.setAlpha(defaultButton.getAlpha());
mCustomButton.setPadding(defaultButton.getPaddingLeft(), defaultButton.defaultButton(),
defaultButton.getPaddingRight(), defaultButton.getPaddingBottom());
// apply layout settings to custom button view
mCustomButton.setLayoutParams(customButtonLayoutParams);
mCustomButton.setVisibility(View.VISIBLE);
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
} catch (Exception ex) {
ex.printStackTrace();
}
}
and enabled Show layout boundaries
option in Developer Options
you should get something like that:
As you can see custom button has exactly same size as default button layout and placed exactly below it.
For better result it's necessary to adjust custom button glyph (padding, transparency, colors, etc.)
Or may be easiest way: don't use default Google Maps "GoogleMapMyLocationButton"
button at all - set it's Enabled property to false
(mGoogleMap.getUiSettings().setMyLocationButtonEnabled(false);
) but use custom layout with button with same icon and functionality emulated by GoogleMap.animateCamera()
on same layout with "target home" custom button.
Upvotes: 2
Reputation: 26198
You have a dpi problems in your posted image, Also in your posted xml you are only using 1 attribute values for all devices android:layout_marginRight="11.5dp"
which will fail in other device with higher dpi, except the one you first tried it on.
solution:
Use the values folder with dpi click here to know about it.
What you need is to create a dimens attribute on each of the dpi folder ldpi, hdpi, etc. for the margin
sample:
<resources>
<dimen name="margin_right">11.5dp</dimen> //this is located in hdpi values dimension
</resources>
and another in xhdpi
<resources>
<dimen name="margin_right">greater than hdpi</dimen> //this is located in xhdpi values dimension
</resources>
to use it is to just call @dimension
android:layout_marginRight="@dimension/margin_right"
now using this solution will enable your device to pick the right value of the margin on different devices.
Upvotes: -1