[android] #2273 - Added InfoWindowView, Refactored InfoWindow to take in account margins/offset, exposed margin of InfoWindow as configurable
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
package com.mapbox.mapboxsdk.annotations;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.PointF;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.mapbox.mapboxsdk.R;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.views.MapView;
|
||||
|
||||
@@ -28,10 +31,7 @@ public final class InfoWindow {
|
||||
public InfoWindow(int layoutResId, MapView mapView) {
|
||||
mMapView = mapView;
|
||||
mIsVisible = false;
|
||||
Context context = mapView.getContext();
|
||||
LayoutInflater inflater =
|
||||
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
mView = inflater.inflate(layoutResId, (ViewGroup) mapView, false);
|
||||
mView = LayoutInflater.from(mapView.getContext()).inflate(layoutResId, mapView, false);
|
||||
|
||||
if (mTitleId == 0) {
|
||||
setResIds(mapView.getContext());
|
||||
@@ -52,10 +52,6 @@ public final class InfoWindow {
|
||||
public InfoWindow(View view, MapView mapView) {
|
||||
mMapView = mapView;
|
||||
mIsVisible = false;
|
||||
ViewGroup parent = (ViewGroup) mapView.getParent();
|
||||
Context context = mapView.getContext();
|
||||
LayoutInflater inflater =
|
||||
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
mView = view;
|
||||
|
||||
// default behavior: close it when clicking on the tooltip:
|
||||
@@ -83,13 +79,67 @@ public final class InfoWindow {
|
||||
MapView.LayoutParams lp = new MapView.LayoutParams(MapView.LayoutParams.WRAP_CONTENT, MapView.LayoutParams.WRAP_CONTENT);
|
||||
mView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
|
||||
|
||||
// Calculate default Android x,y coordinate
|
||||
PointF coords = mMapView.toScreenLocation(position);
|
||||
double y = mMapView.getTopOffsetPixelsForAnnotationSymbol(object.getSprite());
|
||||
float x = coords.x - (mView.getMeasuredWidth() / 2);
|
||||
float y = (float) mMapView.getTopOffsetPixelsForAnnotationSymbol(object.getSprite());
|
||||
y = y * mMapView.getScreenDensity();
|
||||
y += coords.y - mView.getMeasuredHeight();
|
||||
|
||||
lp.leftMargin = (int) coords.x - (mView.getMeasuredWidth() / 2);
|
||||
// Add y because it's a negative value
|
||||
lp.topMargin = (int) coords.y - mView.getMeasuredHeight() + (int) y;
|
||||
// if getTopOffsetPixelsForAnnotationSymbol lands
|
||||
// float x = coords.x - (mView.getMeasuredWidth() / 2) + offsetX;
|
||||
// float y = coords.y - mView.getMeasuredHeight() + offsetY;
|
||||
|
||||
// get right/left popup window
|
||||
float right = x + mView.getMeasuredWidth();
|
||||
float left = x;
|
||||
|
||||
// get right/left map view
|
||||
float mapRight = mMapView.getRight();
|
||||
float mapLeft = mMapView.getLeft();
|
||||
|
||||
if (mView instanceof InfoWindowView) {
|
||||
// only apply repositioning/margin for InfoWindowView
|
||||
Resources resources = mMapView.getContext().getResources();
|
||||
float margin = resources.getDimension(R.dimen.infowindow_margin);
|
||||
float tipViewOffset = resources.getDimension(R.dimen.infowindow_tipview_width) / 2;
|
||||
float tipViewMarginLeft = mView.getMeasuredWidth() / 2 - tipViewOffset;
|
||||
|
||||
// fit screen on right
|
||||
if (right > mMapView.getRight()) {
|
||||
x -= right - mapRight;
|
||||
tipViewMarginLeft += right - mapRight + tipViewOffset;
|
||||
right = x + mView.getMeasuredWidth();
|
||||
}
|
||||
|
||||
// fit screen left
|
||||
if (left < mMapView.getLeft()) {
|
||||
x += mapLeft - left;
|
||||
tipViewMarginLeft -= mapLeft - left + tipViewOffset;
|
||||
left = x;
|
||||
}
|
||||
|
||||
// Add margin right
|
||||
if (mapRight - right < margin) {
|
||||
x -= margin - (mapRight - right);
|
||||
tipViewMarginLeft += margin - (mapRight - right) - tipViewOffset;
|
||||
left = x;
|
||||
}
|
||||
|
||||
// Add margin left
|
||||
if (left - mapLeft < margin) {
|
||||
x += margin - (left - mapLeft);
|
||||
tipViewMarginLeft -= (margin - (left - mapLeft)) - tipViewOffset;
|
||||
}
|
||||
|
||||
// Adjust tipView
|
||||
InfoWindowView infoWindowView = (InfoWindowView) mView;
|
||||
infoWindowView.setTipViewMarginLeft((int) tipViewMarginLeft);
|
||||
}
|
||||
|
||||
// set anchor popupwindowview
|
||||
mView.setX(x);
|
||||
mView.setY(y);
|
||||
|
||||
close(); //if it was already opened
|
||||
mMapView.addView(mView, lp);
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.mapbox.mapboxsdk.annotations;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import com.mapbox.mapboxsdk.R;
|
||||
|
||||
public class InfoWindowView extends RelativeLayout{
|
||||
|
||||
private InfoWindowTipView mTipView;
|
||||
|
||||
public InfoWindowView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public InfoWindowView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public InfoWindowView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
initialize(context);
|
||||
}
|
||||
|
||||
private void initialize(Context context){
|
||||
LayoutInflater.from(context).inflate(R.layout.infowindow_content, this);
|
||||
mTipView = (InfoWindowTipView) findViewById(R.id.infowindow_tipview);
|
||||
}
|
||||
|
||||
public void setTipViewMarginLeft(int marginLeft){
|
||||
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) mTipView.getLayoutParams();
|
||||
layoutParams.leftMargin = marginLeft;
|
||||
}
|
||||
}
|
||||
@@ -202,7 +202,7 @@ public class Marker extends Annotation {
|
||||
*/
|
||||
private InfoWindow getInfoWindow() {
|
||||
if (infoWindow == null) {
|
||||
infoWindow = new InfoWindow(R.layout.infowindow, mapView);
|
||||
infoWindow = new InfoWindow(R.layout.infowindow_view, mapView);
|
||||
}
|
||||
return infoWindow;
|
||||
}
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
<resources>
|
||||
<!--Add references to exposed resources-->
|
||||
<public name="AttributionAlertDialogStyle" type="style" />
|
||||
<public name="infowindow_margin" type="dimen" />
|
||||
</resources>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<LinearLayout
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/infowindow_content"
|
||||
android:background="@color/white"
|
||||
android:padding="5dp"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -45,8 +45,10 @@
|
||||
</LinearLayout>
|
||||
|
||||
<com.mapbox.mapboxsdk.annotations.InfoWindowTipView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="10dp"/>
|
||||
android:id="@+id/infowindow_tipview"
|
||||
android:layout_below="@+id/infowindow_content"
|
||||
android:layout_width="@dimen/infowindow_tipview_width"
|
||||
android:layout_height="8dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.mapbox.mapboxsdk.annotations.InfoWindowView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="infowindow_tipview_width">16dp</dimen>
|
||||
<dimen name="infowindow_margin">8dp</dimen>
|
||||
</resources>
|
||||
@@ -34,7 +34,7 @@ public class InfoWindowAdapterActivityTest extends BaseTest {
|
||||
|
||||
@Test
|
||||
public void testSanity() {
|
||||
onView(withId(R.id.secondMapView))
|
||||
onView(withId(R.id.mapView))
|
||||
.check(matches(isDisplayed()));
|
||||
}
|
||||
|
||||
|
||||
@@ -29,12 +29,17 @@
|
||||
android:name=".InfoWindowAdapterActivity"
|
||||
android:label="@string/activity_infowindow_adapter" />
|
||||
|
||||
<activity
|
||||
android:name=".InfoWindowActivity"
|
||||
android:label="@string/activity_info_window" />
|
||||
|
||||
<activity
|
||||
android:name=".MapFragmentActivity"
|
||||
android:label="@string/activity_map_fragment" />
|
||||
|
||||
<activity android:name=".PressForMarkerActivity"
|
||||
android:label="@string/activity_press_for_marker"/>
|
||||
<activity
|
||||
android:name=".PressForMarkerActivity"
|
||||
android:label="@string/activity_press_for_marker" />
|
||||
|
||||
<meta-data
|
||||
android:name="io.fabric.ApiKey"
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.mapbox.mapboxsdk.testapp;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
|
||||
import com.mapbox.mapboxsdk.constants.Style;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.utils.ApiAccess;
|
||||
import com.mapbox.mapboxsdk.views.MapView;
|
||||
|
||||
public class InfoWindowActivity extends AppCompatActivity {
|
||||
|
||||
private MapView mMapView;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_infowindow);
|
||||
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
actionBar.setDisplayShowHomeEnabled(true);
|
||||
}
|
||||
|
||||
mMapView = (MapView) findViewById(R.id.mapView);
|
||||
mMapView.setAccessToken(ApiAccess.getToken(this));
|
||||
mMapView.onCreate(savedInstanceState);
|
||||
mMapView.setStyle(Style.MAPBOX_STREETS);
|
||||
mMapView.setCenterCoordinate(new LatLng(38.897705003219784, -77.03655168667463));
|
||||
mMapView.setZoomLevel(15);
|
||||
|
||||
mMapView.addMarker(new MarkerOptions()
|
||||
.title("Intersection")
|
||||
.snippet("H St NW with 15th St NW")
|
||||
.position(new LatLng(38.9002073, -77.03364419)));
|
||||
|
||||
mMapView.addMarker(new MarkerOptions()
|
||||
.title("White House")
|
||||
.snippet("The official residence and principal workplace of the President of the United States, located at 1600 Pennsylvania Avenue NW in Washington, D.C. It has been the residence of every U.S. president since John Adams in 1800.")
|
||||
.position(new LatLng(38.897705003219784, -77.03655168667463)));
|
||||
|
||||
mMapView.addMarker(new MarkerOptions().title("Intersection")
|
||||
.snippet("E St NW with 17th St NW")
|
||||
.position(new LatLng(38.8954236, -77.0394623)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mMapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mMapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mMapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mMapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mMapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mMapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mMapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
onBackPressed();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,8 +18,6 @@ import com.mapbox.mapboxsdk.views.MapView;
|
||||
|
||||
public class InfoWindowAdapterActivity extends AppCompatActivity {
|
||||
|
||||
private static final String TAG = "InfoWindowAdapter";
|
||||
|
||||
private MapView mMapView;
|
||||
|
||||
@Override
|
||||
@@ -27,7 +25,7 @@ public class InfoWindowAdapterActivity extends AppCompatActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_infowindow_adapter);
|
||||
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.secondToolBar);
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
@@ -36,7 +34,7 @@ public class InfoWindowAdapterActivity extends AppCompatActivity {
|
||||
actionBar.setDisplayShowHomeEnabled(true);
|
||||
}
|
||||
|
||||
mMapView = (MapView) findViewById(R.id.secondMapView);
|
||||
mMapView = (MapView) findViewById(R.id.mapView);
|
||||
mMapView.setAccessToken(ApiAccess.getToken(this));
|
||||
mMapView.onCreate(savedInstanceState);
|
||||
mMapView.setStyle(Style.MAPBOX_STREETS);
|
||||
@@ -74,36 +72,34 @@ public class InfoWindowAdapterActivity extends AppCompatActivity {
|
||||
return marker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch onStart() to all fragments. Ensure any created loaders are
|
||||
* now started.
|
||||
*/
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mMapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mMapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mMapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mMapView.onStop();
|
||||
}
|
||||
|
||||
// Called when our app goes into the background
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
mMapView.onPause();
|
||||
}
|
||||
|
||||
// Called when our app comes into the foreground
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
mMapView.onResume();
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mMapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -112,11 +108,9 @@ public class InfoWindowAdapterActivity extends AppCompatActivity {
|
||||
mMapView.onDestroy();
|
||||
}
|
||||
|
||||
// Called when the system is running low on memory
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
|
||||
mMapView.onLowMemory();
|
||||
}
|
||||
|
||||
|
||||
@@ -294,19 +294,10 @@ public class MainActivity extends AppCompatActivity {
|
||||
startActivity(new Intent(getApplicationContext(), PressForMarkerActivity.class));
|
||||
return true;
|
||||
|
||||
/*
|
||||
case R.id.followNone:
|
||||
mMapView.setUserLocationTrackingMode(MapView.UserLocationTrackingMode.NONE);
|
||||
case R.id.action_info_window:
|
||||
startActivity(new Intent(getApplicationContext(), InfoWindowActivity.class));
|
||||
return true;
|
||||
|
||||
case R.id.followFollow:
|
||||
mMapView.setUserLocationTrackingMode(MapView.UserLocationTrackingMode.FOLLOW);
|
||||
return true;
|
||||
|
||||
case R.id.followBearing:
|
||||
mMapView.setUserLocationTrackingMode(MapView.UserLocationTrackingMode.FOLLOW_BEARING);
|
||||
return true;
|
||||
*/
|
||||
default:
|
||||
return changeMapStyle(menuItem.getItemId());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/primary"
|
||||
android:minHeight="?attr/actionBarSize"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
|
||||
|
||||
<com.mapbox.mapboxsdk.views.MapView
|
||||
android:id="@+id/mapView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -5,7 +5,7 @@
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/secondToolBar"
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/primary"
|
||||
@@ -13,7 +13,7 @@
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
|
||||
|
||||
<com.mapbox.mapboxsdk.views.MapView
|
||||
android:id="@+id/secondMapView"
|
||||
android:id="@+id/mapView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
|
||||
@@ -73,11 +73,6 @@
|
||||
<item android:id="@+id/testsMenu"
|
||||
android:title="@string/navdrawer_menu_title_individual_tests">
|
||||
<menu>
|
||||
<item
|
||||
android:id="@+id/action_info_window_adapter"
|
||||
android:checkable="false"
|
||||
android:icon="@drawable/ic_filter_none_white_24dp"
|
||||
android:title="@string/action_info_window_adapter" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_map_fragment"
|
||||
@@ -85,10 +80,23 @@
|
||||
android:icon="@drawable/ic_widgets_white_24dp"
|
||||
android:title="@string/action_map_fragment" />
|
||||
|
||||
<item android:id="@+id/action_press_for_marker"
|
||||
android:checkable="false"
|
||||
android:icon="@drawable/ic_pin_drop_white_24dp"
|
||||
android:title="@string/action_press_for_marker"/>
|
||||
<item
|
||||
android:id="@+id/action_info_window"
|
||||
android:checkable="false"
|
||||
android:icon="@drawable/ic_filter_none_white_24dp"
|
||||
android:title="@string/action_info_window" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_info_window_adapter"
|
||||
android:checkable="false"
|
||||
android:icon="@drawable/ic_filter_none_white_24dp"
|
||||
android:title="@string/action_info_window_adapter" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_press_for_marker"
|
||||
android:checkable="false"
|
||||
android:icon="@drawable/ic_pin_drop_white_24dp"
|
||||
android:title="@string/action_press_for_marker"/>
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<string name="activity_infowindow_adapter">InfoWindow Adapter</string>
|
||||
<string name="activity_map_fragment">Map Fragment Activity</string>
|
||||
<string name="activity_press_for_marker">Press For Marker Activity</string>
|
||||
<string name="activity_info_window">InfoWindow Activity</string>
|
||||
|
||||
<string name="navdrawer_menu_title_mainactivity_controls">Main Activity Controls</string>
|
||||
<string name="navdrawer_menu_title_mainactivity_styles">Main Activity Styles</string>
|
||||
@@ -21,6 +22,7 @@
|
||||
<string name="action_info_window_adapter">InfoWindow Adapter</string>
|
||||
<string name="action_map_fragment">MapFragment</string>
|
||||
<string name="action_press_for_marker">Press For Marker</string>
|
||||
<string name="action_info_window">InfoWindow</string>
|
||||
|
||||
<string name="label_fps">FPS:</string>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user