From 26108812d4da927c4aaf19c76a8e49a076f2266e Mon Sep 17 00:00:00 2001 From: Nathan Varner Date: Tue, 7 Mar 2023 02:28:13 -0500 Subject: [PATCH] [android] Add basic turn lanes GUI The Android UI takes in turn lanes from native code and displays the same number of turn lanes at the top of the navigation interface. It does not yet show which lane(s) to take, or how you can turn from a lane. Needed for: #1404 Signed-off-by: Nathan Varner --- android/res/layout/layout_nav_top.xml | 11 +++ android/res/layout/nav_lanes.xml | 20 ++++++ android/res/layout/nav_single_lane.xml | 12 ++++ android/res/values/dimens.xml | 1 + android/res/values/themes-attrs.xml | 1 + android/res/values/themes-base.xml | 2 + .../app/organicmaps/routing/LanesAdapter.java | 71 +++++++++++++++++++ .../routing/NavigationController.java | 23 ++++++ 8 files changed, 141 insertions(+) create mode 100644 android/res/layout/nav_lanes.xml create mode 100644 android/res/layout/nav_single_lane.xml create mode 100644 android/src/app/organicmaps/routing/LanesAdapter.java diff --git a/android/res/layout/layout_nav_top.xml b/android/res/layout/layout_nav_top.xml index 88759a3cf1..08519e5817 100644 --- a/android/res/layout/layout_nav_top.xml +++ b/android/res/layout/layout_nav_top.xml @@ -104,4 +104,15 @@ tools:src="@drawable/ic_then_left_sharp"/> + + + + + \ No newline at end of file diff --git a/android/res/layout/nav_lanes.xml b/android/res/layout/nav_lanes.xml new file mode 100644 index 0000000000..9db6f67607 --- /dev/null +++ b/android/res/layout/nav_lanes.xml @@ -0,0 +1,20 @@ + + + + + diff --git a/android/res/layout/nav_single_lane.xml b/android/res/layout/nav_single_lane.xml new file mode 100644 index 0000000000..02943a6ad6 --- /dev/null +++ b/android/res/layout/nav_single_lane.xml @@ -0,0 +1,12 @@ + + diff --git a/android/res/values/dimens.xml b/android/res/values/dimens.xml index cb2367285b..e408417873 100644 --- a/android/res/values/dimens.xml +++ b/android/res/values/dimens.xml @@ -114,6 +114,7 @@ 70sp 64dp 360dp + 48dp @dimen/margin_half 64dp diff --git a/android/res/values/themes-attrs.xml b/android/res/values/themes-attrs.xml index 3e82d4eb99..c7dd7377c5 100644 --- a/android/res/values/themes-attrs.xml +++ b/android/res/values/themes-attrs.xml @@ -19,6 +19,7 @@ + diff --git a/android/res/values/themes-base.xml b/android/res/values/themes-base.xml index 7c6d4866fa..7ba5288e45 100644 --- a/android/res/values/themes-base.xml +++ b/android/res/values/themes-base.xml @@ -45,6 +45,7 @@ @drawable/bg_nav_next_turn @drawable/bg_nav_next_next_turn + @color/base_accent @drawable/button @color/button_text @@ -179,6 +180,7 @@ @drawable/bg_nav_next_turn_night @drawable/bg_nav_next_next_turn_night + @color/base_accent_night @drawable/button_night @color/button_text_night diff --git a/android/src/app/organicmaps/routing/LanesAdapter.java b/android/src/app/organicmaps/routing/LanesAdapter.java new file mode 100644 index 0000000000..eb02b47760 --- /dev/null +++ b/android/src/app/organicmaps/routing/LanesAdapter.java @@ -0,0 +1,71 @@ +package app.organicmaps.routing; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; +import app.organicmaps.R; +import app.organicmaps.widget.ArrowView; + +import java.util.ArrayList; +import java.util.List; + +public class LanesAdapter extends RecyclerView.Adapter +{ + @NonNull + private final List mItems = new ArrayList<>(); + + @NonNull + @Override + public LanesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) + { + final LayoutInflater inflater = LayoutInflater.from(parent.getContext()); + final View root = inflater.inflate(R.layout.nav_single_lane, parent, false); + return new LanesViewHolder(root); + } + + @Override + public void onBindViewHolder(@NonNull LanesViewHolder holder, int position) + { + holder.bind(mItems.get(position)); + } + + @Override + public int getItemCount() + { + return mItems.size(); + } + + public void setItems(@NonNull List items) + { + mItems.clear(); + mItems.addAll(items); + notifyDataSetChanged(); + } + + public void clearItems() + { + boolean alreadyEmpty = mItems.isEmpty(); + mItems.clear(); + if (!alreadyEmpty) + notifyDataSetChanged(); + } + + static class LanesViewHolder extends RecyclerView.ViewHolder + { + @NonNull + private final ArrowView mArrow; + + public LanesViewHolder(@NonNull View itemView) + { + super(itemView); + mArrow = itemView.findViewById(R.id.lane_image); + } + + void bind(@NonNull SingleLaneInfo info) + { + } + } +} diff --git a/android/src/app/organicmaps/routing/NavigationController.java b/android/src/app/organicmaps/routing/NavigationController.java index 36a3eb887a..2110c9bbea 100644 --- a/android/src/app/organicmaps/routing/NavigationController.java +++ b/android/src/app/organicmaps/routing/NavigationController.java @@ -20,6 +20,7 @@ import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; +import androidx.recyclerview.widget.RecyclerView; import com.google.android.material.bottomsheet.BottomSheetBehavior; import app.organicmaps.Framework; import app.organicmaps.MwmActivity; @@ -32,6 +33,8 @@ import app.organicmaps.widget.menu.NavMenu; import app.organicmaps.util.UiUtils; import app.organicmaps.util.Utils; +import java.util.Arrays; + public class NavigationController implements Application.ActivityLifecycleCallbacks, TrafficManager.TrafficCallback, NavMenu.NavMenuListener @@ -50,6 +53,11 @@ public class NavigationController implements Application.ActivityLifecycleCallba private final View mStreetFrame; private final TextView mNextStreet; + @NonNull + private final RecyclerView mLanes; + @NonNull + private final LanesAdapter mLanesAdapter; + @NonNull private final MapButtonsController mMapButtonsController; @@ -90,6 +98,12 @@ public class NavigationController implements Application.ActivityLifecycleCallba }); } + private void initLanesRecycler() + { + mLanes.setAdapter(mLanesAdapter); + mLanes.setNestedScrollingEnabled(false); + } + public NavigationController(AppCompatActivity activity, @NonNull MapButtonsController mapButtonsController, View.OnClickListener onSettingsClickListener) { mFrame = activity.findViewById(R.id.navigation_frame); @@ -112,6 +126,10 @@ public class NavigationController implements Application.ActivityLifecycleCallba mStreetFrame = topFrame.findViewById(R.id.street_frame); mNextStreet = mStreetFrame.findViewById(R.id.street); + mLanes = topFrame.findViewById(R.id.lanes); + mLanesAdapter = new LanesAdapter(); + initLanesRecycler(); + // Show a blank view below the navbar to hide the menu content final View navigationBarBackground = mFrame.findViewById(R.id.nav_bottom_sheet_nav_bar); final View nextTurnContainer = mFrame.findViewById(R.id.nav_next_turn_container); @@ -185,6 +203,11 @@ public class NavigationController implements Application.ActivityLifecycleCallba UiUtils.showIf(info.nextCarDirection.containsNextTurn(), mNextNextTurnFrame); if (info.nextCarDirection.containsNextTurn()) info.nextCarDirection.setNextTurnDrawable(mNextNextTurnImage); + + if (info.lanes != null) + mLanesAdapter.setItems(Arrays.asList(info.lanes)); + else + mLanesAdapter.clearItems(); } private void updatePedestrian(RoutingInfo info)