[android] Fix my position arrow during navigation

Fixes #4855
Fixes #3441
Fixes #4456

Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
This commit is contained in:
Roman Tsisyk 2022-09-20 11:11:50 +03:00
parent 05ae3695fe
commit 2ddfa9ff52
10 changed files with 95 additions and 83 deletions

View file

@ -668,6 +668,11 @@ void Framework::SetupWidget(gui::EWidget widget, float x, float y, dp::Anchor an
m_guiPositions[widget] = gui::Position(m2::PointF(x, y), anchor);
}
void Framework::UpdateMyPositionRoutingOffset(int offsetY)
{
NativeFramework()->UpdateMyPositionRoutingOffset(false, offsetY);
}
void Framework::ApplyWidgets()
{
gui::TWidgetsLayoutInfo layout;

View file

@ -180,6 +180,7 @@ namespace android
void SetChoosePositionMode(bool isChoosePositionMode, bool isBusiness, bool hasPosition, m2::PointD const & position);
bool GetChoosePositionMode();
void UpdateMyPositionRoutingOffset(int offsetY);
void SetupWidget(gui::EWidget widget, float x, float y, dp::Anchor anchor);
void ApplyWidgets();
void CleanWidgets();

View file

@ -96,6 +96,12 @@ Java_app_organicmaps_Map_nativeResumeSurfaceRendering(JNIEnv *, jclass)
g_framework->ResumeSurfaceRendering();
}
JNIEXPORT void JNICALL
Java_app_organicmaps_Map_nativeUpdateMyPositionRoutingOffset(JNIEnv * env, jclass clazz, int offsetY)
{
g_framework->UpdateMyPositionRoutingOffset(offsetY);
}
JNIEXPORT void JNICALL
Java_app_organicmaps_Map_nativeApplyWidgets(JNIEnv *, jclass)
{

View file

@ -81,7 +81,7 @@ public final class Map
* @param offsetY Pixel offset from the right. -1 to keep the previous value.
* @param forceRedraw True to force the compass to redraw
*/
public void setupCompass(final Context context, int offsetX, int offsetY, boolean forceRedraw)
public void updateCompassOffset(final Context context, int offsetX, int offsetY, boolean forceRedraw)
{
final int x = offsetX < 0 ? mCurrentCompassOffsetX : offsetX;
final int y = offsetY < 0 ? mCurrentCompassOffsetY : offsetY;
@ -107,16 +107,27 @@ public final class Map
* @param offsetX Pixel offset from the left. -1 to keep the previous value.
* @param offsetY Pixel offset from the bottom. -1 to keep the previous value.
*/
public void setupBottomWidgetsOffset(final Context context, int offsetX, int offsetY)
public void updateBottomWidgetsOffset(final Context context, int offsetX, int offsetY)
{
final int x = offsetX < 0 ? mBottomWidgetOffsetX : offsetX;
final int y = offsetY < 0 ? mBottomWidgetOffsetY : offsetY;
setupRuler(context, x, y);
setupAttribution(context, x, y);
updateRulerOffset(context, x, y);
updateAttributionOffset(context, x, y);
mBottomWidgetOffsetX = x;
mBottomWidgetOffsetY = y;
}
/**
* Moves my position arrow to the given offset.
*
* @param context Context.
* @param offsetY Pixel offset from the bottom.
*/
public void updateMyPositionRoutingOffset(final Context context, int offsetY)
{
nativeUpdateMyPositionRoutingOffset(offsetY);
}
public void onSurfaceCreated(final Context context, final Surface surface, Rect surfaceFrame, int surfaceDpi)
{
if (isThemeChangingProcess(context))
@ -299,12 +310,12 @@ public final class Map
mWidth = width;
nativeCleanWidgets();
setupBottomWidgetsOffset(context, mBottomWidgetOffsetX, mBottomWidgetOffsetY);
updateBottomWidgetsOffset(context, mBottomWidgetOffsetX, mBottomWidgetOffsetY);
nativeSetupWidget(WIDGET_SCALE_FPS_LABEL, UiUtils.dimen(context, R.dimen.margin_base), UiUtils.dimen(context, R.dimen.margin_base), ANCHOR_LEFT_TOP);
setupCompass(context, mCurrentCompassOffsetX, mCurrentCompassOffsetY, false);
updateCompassOffset(context, mCurrentCompassOffsetX, mCurrentCompassOffsetY, false);
}
private void setupRuler(final Context context, int offsetX, int offsetY)
private void updateRulerOffset(final Context context, int offsetX, int offsetY)
{
nativeSetupWidget(WIDGET_RULER,
UiUtils.dimen(context, R.dimen.margin_ruler) + offsetX,
@ -314,7 +325,7 @@ public final class Map
nativeApplyWidgets();
}
private void setupAttribution(final Context context, int offsetX, int offsetY)
private void updateAttributionOffset(final Context context, int offsetX, int offsetY)
{
nativeSetupWidget(WIDGET_COPYRIGHT,
UiUtils.dimen(context, R.dimen.margin_ruler) + offsetX,
@ -350,6 +361,7 @@ public final class Map
// Widgets
private static native void nativeApplyWidgets();
private static native void nativeCleanWidgets();
private static native void nativeUpdateMyPositionRoutingOffset(int offsetY);
private static native void nativeSetupWidget(int widget, float x, float y, int anchor);
private static native void nativeCompassUpdated(double north, boolean forceRedraw);

View file

@ -23,14 +23,19 @@ public class MapFragment extends BaseMwmFragment implements View.OnTouchListener
private static final String TAG = MapFragment.class.getSimpleName();
private final Map mMap = new Map();
public void adjustCompass(int offsetX, int offsetY)
public void updateCompassOffset(int offsetX, int offsetY)
{
mMap.setupCompass(requireContext(), offsetX, offsetY, true);
mMap.updateCompassOffset(requireContext(), offsetX, offsetY, true);
}
public void adjustBottomWidgets(int offsetX, int offsetY)
public void updateBottomWidgetsOffset(int offsetX, int offsetY)
{
mMap.setupBottomWidgetsOffset(requireContext(), offsetX, offsetY);
mMap.updateBottomWidgetsOffset(requireContext(), offsetX, offsetY);
}
public void updateMyPositionRoutingOffset(int offsetY)
{
mMap.updateMyPositionRoutingOffset(requireContext(), offsetY);
}
public void destroySurface()

View file

@ -428,11 +428,11 @@ public class MwmActivity extends BaseMwmFragmentActivity
// For the first loading, set compass top margin to status bar size
// The top inset will be then be updated by the routing controller
if (mCurrentWindowInsets == null)
adjustCompass(windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).top, windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).right);
updateCompassOffset(windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).top, windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).right);
else
adjustCompass(-1, windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).right);
updateCompassOffset(-1, windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).right);
refreshLightStatusBar();
adjustBottomWidgets(windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).left);
updateBottomWidgetsOffset(windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).left);
mCurrentWindowInsets = windowInsets;
return windowInsets;
});
@ -465,7 +465,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
removeCurrentFragment(false);
}
mNavigationController = new NavigationController(this, mMapButtonsController, v -> onSettingsOptionSelected());
mNavigationController = new NavigationController(this, mMapButtonsController, v -> onSettingsOptionSelected(), this::updateBottomWidgetsOffset);
//TrafficManager.INSTANCE.attach(mNavigationController);
initMainMenu();
@ -629,7 +629,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
this::onMapButtonClick,
(v) -> closeSearchToolbar(true, true),
mPlacePageController,
this::adjustBottomWidgets);
this::updateBottomWidgetsOffset);
FragmentTransaction transaction = getSupportFragmentManager()
@ -811,7 +811,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
private void initMainMenu()
{
mMainMenu = new MainMenu(findViewById(R.id.menu_frame), this::adjustBottomWidgets);
mMainMenu = new MainMenu(findViewById(R.id.menu_frame), this::updateBottomWidgetsOffset);
if (mIsTabletLayout)
{
@ -1205,43 +1205,46 @@ public class MwmActivity extends BaseMwmFragmentActivity
}
}
void adjustCompass(int offsetY)
void updateCompassOffset(int offsetY)
{
adjustCompass(offsetY, -1);
updateCompassOffset(offsetY, -1);
}
void adjustCompass(int offsetY, int offsetX)
void updateCompassOffset(int offsetY, int offsetX)
{
if (mMapFragment == null || !mMapFragment.isAdded())
return;
mMapFragment.adjustCompass(offsetX, offsetY);
mMapFragment.updateCompassOffset(offsetX, offsetY);
final double north = LocationHelper.INSTANCE.getSavedNorth();
if (!Double.isNaN(north))
Map.onCompassUpdated(north, true);
}
public void adjustBottomWidgets()
public void updateBottomWidgetsOffset()
{
adjustBottomWidgets(-1);
updateBottomWidgetsOffset(-1);
}
public void adjustBottomWidgets(int offsetX)
public void updateBottomWidgetsOffset(int offsetX)
{
if (mMapFragment == null || !mMapFragment.isAdded())
return;
int mapButtonsHeight = 0;
int mainMenuHeight = 0;
int offsetY = mNavBarHeight;
if (mMapButtonsController != null)
mapButtonsHeight = (int) mMapButtonsController.getBottomButtonsHeight() + mNavBarHeight;
offsetY = Math.max(offsetY, (int) mMapButtonsController.getBottomButtonsHeight() + mNavBarHeight);
if (mMainMenu != null)
mainMenuHeight = mMainMenu.getMenuHeight();
offsetY = Math.max(offsetY, mMainMenu.getMenuHeight());
final int y = Math.max(Math.max(mapButtonsHeight, mainMenuHeight), mNavBarHeight);
final View navBottomSheetLineFrame = findViewById(R.id.line_frame);
final View navBottomSheetNavBar = findViewById(R.id.nav_bottom_sheet_nav_bar);
if (navBottomSheetLineFrame != null)
offsetY = Math.max(offsetY, navBottomSheetLineFrame.getHeight() + navBottomSheetNavBar.getHeight());
mMapFragment.adjustBottomWidgets(offsetX, y);
mMapFragment.updateBottomWidgetsOffset(offsetX, offsetY);
mMapFragment.updateMyPositionRoutingOffset(offsetY);
}
@Override
@ -1455,7 +1458,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
@Override
public boolean run(@NonNull MwmActivity target)
{
adjustCompass(offsetY);
updateCompassOffset(offsetY);
return true;
}
});

View file

@ -106,10 +106,11 @@ public class NavigationController implements Application.ActivityLifecycleCallba
mLanes.setNestedScrollingEnabled(false);
}
public NavigationController(AppCompatActivity activity, @NonNull MapButtonsController mapButtonsController, View.OnClickListener onSettingsClickListener)
public NavigationController(AppCompatActivity activity, @NonNull MapButtonsController mapButtonsController,
View.OnClickListener onSettingsClickListener, NavMenu.OnMenuSizeChangedListener onMenuSizeChangedListener)
{
mFrame = activity.findViewById(R.id.navigation_frame);
mNavMenu = new NavMenu(activity, this);
mNavMenu = new NavMenu(activity, this, onMenuSizeChangedListener);
mOnSettingsClickListener = onSettingsClickListener;
mMapButtonsController = mapButtonsController;

View file

@ -14,6 +14,7 @@ import app.organicmaps.R;
import app.organicmaps.location.LocationHelper;
import app.organicmaps.routing.RoutingInfo;
import app.organicmaps.sound.TtsPlayer;
import app.organicmaps.util.log.Logger;
import app.organicmaps.widget.FlatProgressView;
import app.organicmaps.util.Graphics;
import app.organicmaps.util.StringUtils;
@ -49,12 +50,21 @@ public class NavMenu
private int currentPeekHeight = 0;
public NavMenu(AppCompatActivity activity, NavMenuListener navMenuListener)
public interface OnMenuSizeChangedListener
{
void OnMenuSizeChange();
}
private final OnMenuSizeChangedListener mOnMenuSizeChangedListener;
public NavMenu(AppCompatActivity activity, NavMenuListener navMenuListener, OnMenuSizeChangedListener onMenuSizeChangedListener)
{
mActivity = activity;
mNavMenuListener = navMenuListener;
final View bottomFrame = mActivity.findViewById(R.id.nav_bottom_frame);
mHeaderFrame = bottomFrame.findViewById(R.id.line_frame);
mOnMenuSizeChangedListener = onMenuSizeChangedListener;
mHeaderFrame.setOnClickListener(v -> toggleNavMenu());
mHeaderFrame.addOnLayoutChangeListener((view, i, i1, i2, i3, i4, i5, i6, i7) -> setPeekHeight());
mNavBottomSheetBehavior = BottomSheetBehavior.from(mActivity.findViewById(R.id.nav_bottom_sheet));
@ -138,6 +148,7 @@ public class NavMenu
{
currentPeekHeight = headerHeight;
mNavBottomSheetBehavior.setPeekHeight(currentPeekHeight);
mOnMenuSizeChangedListener.OnMenuSizeChange();
}
}

View file

@ -20,46 +20,15 @@ class PlacePageUtils
static void moveViewportUp(@NonNull View placePageView, int viewportMinHeight)
{
placePageView.post(() -> {
View coordinatorLayout = (ViewGroup) placePageView.getParent();
int viewPortWidth = coordinatorLayout.getWidth();
final View coordinatorLayout = (ViewGroup) placePageView.getParent();
final int viewPortWidth = coordinatorLayout.getWidth();
int viewPortHeight = coordinatorLayout.getHeight();
Rect sheetRect = new Rect();
placePageView.getGlobalVisibleRect(sheetRect);
if (sheetRect.top < viewportMinHeight)
return;
if (sheetRect.top >= viewPortHeight)
{
Framework.nativeSetVisibleRect(0, 0, viewPortWidth, viewPortHeight);
return;
}
viewPortHeight -= sheetRect.height();
Framework.nativeSetVisibleRect(0, 0, viewPortWidth, viewPortHeight);
});
}
static void moveViewPortRight(@NonNull View bootomSheet, int viewportMinWidth)
{
bootomSheet.post(() -> {
View coordinatorLayout = (ViewGroup) bootomSheet.getParent();
int viewPortWidth = coordinatorLayout.getWidth();
int viewPortHeight = coordinatorLayout.getHeight();
Rect sheetRect = new Rect();
bootomSheet.getGlobalVisibleRect(sheetRect);
if ((viewPortWidth - sheetRect.right) < viewportMinWidth)
{
Framework.nativeSetVisibleRect((viewPortWidth - viewportMinWidth), 0, viewPortWidth,
viewPortHeight);
return;
}
if (sheetRect.top >= viewPortHeight)
{
if (viewPortHeight >= viewportMinHeight)
Framework.nativeSetVisibleRect(0, 0, viewPortWidth, viewPortHeight);
return;
}
Framework.nativeSetVisibleRect(sheetRect.right, 0, viewPortWidth, viewPortHeight);
});
}

View file

@ -37,7 +37,7 @@ int const kMaxScaleZoomLevel = 16;
int const kDefaultAutoZoom = 16;
double const kUnknownAutoZoom = -1.0;
int GetZoomLevel(ScreenBase const & screen)
inline int GetZoomLevel(ScreenBase const & screen)
{
return static_cast<int>(df::GetZoomLevel(screen.GetScale()));
}
@ -50,6 +50,11 @@ int GetZoomLevel(ScreenBase const & screen, m2::PointD const & position, double
return GetZoomLevel(s);
}
inline double GetVisualScale()
{
return df::VisualParams::Instance().GetVisualScale();
}
// Calculate zoom value in meters per pixel
double CalculateZoomBySpeed(double speedMpS, bool isPerspectiveAllowed)
{
@ -82,7 +87,7 @@ double CalculateZoomBySpeed(double speedMpS, bool isPerspectiveAllowed)
if (scales[i].first >= speedKmpH)
break;
double const vs = df::VisualParams::Instance().GetVisualScale();
double const vs = GetVisualScale();
if (i == 0)
return scales.front().second / vs;
@ -130,7 +135,7 @@ MyPositionController::MyPositionController(Params && params, ref_ptr<DrapeNotifi
, m_autoScale3d(m_autoScale2d)
, m_lastGPSBearingTimer(false)
, m_lastLocationTimestamp(0.0)
, m_positionRoutingOffsetY(kPositionRoutingOffsetY)
, m_positionRoutingOffsetY(kPositionRoutingOffsetY * GetVisualScale())
, m_isDirtyViewport(false)
, m_isDirtyAutoZoom(false)
, m_isPendingAnimation(false)
@ -144,11 +149,6 @@ MyPositionController::MyPositionController(Params && params, ref_ptr<DrapeNotifi
, m_blockAutoZoomNotifyId(DrapeNotifier::kInvalidId)
, m_updateLocationNotifyId(DrapeNotifier::kInvalidId)
{
#ifdef OMIM_OS_ANDROID
/// @todo Hotfix for Android. Suppose that additional offset is needed for system buttons toolbar.
m_positionRoutingOffsetY += Arrow3d::GetMaxBottomSize();
#endif
using namespace location;
m_mode = PendingPosition;
@ -188,10 +188,10 @@ void MyPositionController::OnUpdateScreen(ScreenBase const & screen)
{
m_pixelRect = screen.PixelRectIn3d();
if (m_visiblePixelRect.IsEmptyInterior())
m_visiblePixelRect = m_pixelRect;
SetVisibleViewport(m_pixelRect);
}
void MyPositionController::SetVisibleViewport(const m2::RectD &rect)
void MyPositionController::SetVisibleViewport(m2::RectD const & rect)
{
m_visiblePixelRect = rect;
}
@ -767,14 +767,13 @@ m2::PointD MyPositionController::GetRotationPixelCenter() const
m2::PointD MyPositionController::GetRoutingRotationPixelCenter() const
{
return {m_visiblePixelRect.Center().x,
m_visiblePixelRect.maxY() - m_positionRoutingOffsetY * VisualParams::Instance().GetVisualScale()};
return { m_visiblePixelRect.Center().x, m_visiblePixelRect.maxY() - m_positionRoutingOffsetY };
}
void MyPositionController::UpdateRoutingOffsetY(bool useDefault, int offsetY)
{
/// @todo This function is called on CarPlay only for now.
m_positionRoutingOffsetY = useDefault ? kPositionRoutingOffsetY : offsetY + Arrow3d::GetMaxBottomSize();
double const vs = GetVisualScale();
m_positionRoutingOffsetY = useDefault ? kPositionRoutingOffsetY * vs : offsetY + Arrow3d::GetMaxBottomSize() * vs;
}
m2::PointD MyPositionController::GetDrawablePosition()