-
Notifications
You must be signed in to change notification settings - Fork 320
Added exit signs to the instruction banner and refactored instruction loader #1195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 15 commits
90ae9e3
166228c
d51cb32
b443608
ce4afa3
49e2464
491312f
ee21049
6ccd5d3
c4352f6
fb9c88e
6283b28
4eec682
21ae19b
a44030f
de9a31a
d28ba0b
4c2f6d4
92bc66a
7be09d2
f625092
5f477ae
931a69e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package com.mapbox.services.android.navigation.ui.v5.instruction; | ||
|
|
||
| import com.mapbox.api.directions.v5.models.BannerComponents; | ||
| import com.mapbox.core.utils.TextUtils; | ||
|
|
||
| class AbbreviationVerifier extends NodeVerifier { | ||
| @Override | ||
| boolean isNodeType(BannerComponents bannerComponents) { | ||
| return hasAbbreviation(bannerComponents); | ||
| } | ||
|
|
||
| private boolean hasAbbreviation(BannerComponents components) { | ||
| return !TextUtils.isEmpty(components.abbreviation()); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| package com.mapbox.services.android.navigation.ui.v5.instruction; | ||
|
|
||
| import com.mapbox.api.directions.v5.models.BannerComponents; | ||
|
|
||
| /** | ||
| * Class used to construct a list of BannerComponents to be populated into a TextView | ||
| */ | ||
| class BannerComponentNode { | ||
| BannerComponents bannerComponents; | ||
| int startIndex; | ||
|
|
||
| BannerComponentNode(BannerComponents bannerComponents, int startIndex) { | ||
| this.bannerComponents = bannerComponents; | ||
| this.startIndex = startIndex; | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| return bannerComponents.text(); | ||
| } | ||
|
|
||
| void setStartIndex(int startIndex) { | ||
| this.startIndex = startIndex; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| package com.mapbox.services.android.navigation.ui.v5.instruction; | ||
|
|
||
| import android.support.annotation.NonNull; | ||
| import android.widget.TextView; | ||
|
|
||
| import com.mapbox.api.directions.v5.models.BannerComponents; | ||
| import com.mapbox.api.directions.v5.models.BannerText; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
| class BannerComponentTree { | ||
| private final NodeCreator[] nodeCreators; | ||
| private final List<BannerComponentNode> bannerComponentNodes; | ||
|
|
||
| /** | ||
| * Creates a master coordinator to make sure the coordinators passed in are used appropriately | ||
| * | ||
| * @param nodeCreators coordinators in the order that they should process banner components | ||
| */ | ||
| BannerComponentTree(@NonNull BannerText bannerText, NodeCreator... nodeCreators) { | ||
| this.nodeCreators = nodeCreators; | ||
| bannerComponentNodes = parseBannerComponents(bannerText); | ||
| } | ||
|
|
||
| /** | ||
| * Parses the banner components and processes them using the nodeCreators in the order they | ||
| * were originally passed | ||
| * | ||
| * @param bannerText to parse | ||
| * @return the list of nodes representing the bannerComponents | ||
| */ | ||
| private List<BannerComponentNode> parseBannerComponents(BannerText bannerText) { | ||
| int length = 0; | ||
| List<BannerComponentNode> bannerComponentNodes = new ArrayList<>(); | ||
|
|
||
| for (BannerComponents components : bannerText.components()) { | ||
| BannerComponentNode node = null; | ||
| for (NodeCreator nodeCreator : nodeCreators) { | ||
| if (nodeCreator.isNodeType(components)) { | ||
| node = nodeCreator.setupNode(components, bannerComponentNodes.size(), length, | ||
| bannerText.modifier()); | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| if (node != null) { | ||
| bannerComponentNodes.add(node); | ||
| length += components.text().length(); | ||
| } | ||
| } | ||
|
|
||
| return bannerComponentNodes; | ||
| } | ||
|
|
||
| /** | ||
| * Loads the instruction into the given text view. If things have to be done in a particular order, | ||
| * the coordinator methods preProcess and postProcess can be used. PreProcess should be used to | ||
| * load text into the textView (so there should only be one coordinator calling this method), and | ||
| * postProcess should be used to make changes to that text, i.e., to load images into the textView. | ||
| * | ||
| * @param textView in which to load text and images | ||
| */ | ||
| void loadInstruction(TextView textView) { | ||
| for (NodeCreator nodeCreator : nodeCreators) { | ||
| nodeCreator.preProcess(textView, bannerComponentNodes); | ||
| } | ||
|
|
||
| for (NodeCreator nodeCreator : nodeCreators) { | ||
| nodeCreator.postProcess(textView, bannerComponentNodes); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| package com.mapbox.services.android.navigation.ui.v5.instruction; | ||
|
|
||
| import android.content.Context; | ||
| import android.view.LayoutInflater; | ||
| import android.view.ViewGroup; | ||
| import android.widget.TextView; | ||
|
|
||
| import com.mapbox.api.directions.v5.models.BannerComponents; | ||
| import com.mapbox.services.android.navigation.ui.v5.R; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| class ExitSignCreator extends NodeCreator<BannerComponentNode, ExitSignVerifier> { | ||
| private String exitNumber; | ||
| private int startIndex; | ||
| private TextViewUtils textViewUtils; | ||
| private String modifier; | ||
|
|
||
| ExitSignCreator() { | ||
| super(new ExitSignVerifier()); | ||
| textViewUtils = new TextViewUtils(); | ||
| } | ||
|
|
||
| @Override | ||
| BannerComponentNode setupNode(BannerComponents components, int index, int startIndex, String | ||
| modifier) { | ||
| if (components.type().equals("exit")) { | ||
|
||
| return null; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we return
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @danesfeder this contains the text in the native language representing "exit", but for parity with iOS we are dropping this node (See screenshots, it doesn't say |
||
| } else if (components.type().equals("exit-number")) { | ||
| exitNumber = components.text(); | ||
| this.startIndex = startIndex; | ||
| this.modifier = modifier; | ||
| } | ||
|
|
||
| return new BannerComponentNode(components, startIndex); | ||
| } | ||
|
|
||
| /** | ||
| * One coordinator should override this method, and this should be the coordinator which populates | ||
| * the textView with text. | ||
| * | ||
| * @param textView to populate | ||
| * @param bannerComponentNodes containing instructions | ||
| */ | ||
| @Override | ||
| void postProcess(TextView textView, List<BannerComponentNode> bannerComponentNodes) { | ||
| if (exitNumber != null) { | ||
| LayoutInflater inflater = (LayoutInflater) textView.getContext().getSystemService(Context | ||
| .LAYOUT_INFLATER_SERVICE); | ||
|
|
||
| ViewGroup root = (ViewGroup) textView.getParent(); | ||
|
|
||
| TextView exitSignView; | ||
|
|
||
| if (modifier.equals("left")) { | ||
| exitSignView = (TextView) inflater.inflate(R.layout.exit_sign_view_left, root, false); | ||
| } else { | ||
| exitSignView = (TextView) inflater.inflate(R.layout.exit_sign_view_right, root, false); | ||
| } | ||
|
|
||
| exitSignView.setText(exitNumber); | ||
|
|
||
| textViewUtils.setImageSpan(textView, exitSignView, startIndex, startIndex + exitNumber | ||
| .length()); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package com.mapbox.services.android.navigation.ui.v5.instruction; | ||
|
|
||
| import com.mapbox.api.directions.v5.models.BannerComponents; | ||
|
|
||
| class ExitSignVerifier extends NodeVerifier { | ||
|
|
||
| @Override | ||
| boolean isNodeType(BannerComponents bannerComponents) { | ||
| return bannerComponents.type().equals("exit") || bannerComponents.type().equals("exit-number"); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed internally, should we remove this constructor? IMO it's not adding any value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Guardiola31337 What discussion? Are you talking about the discussion about Dan's PR? If you are, you said that you didn't feel strongly about that either way. I think this is adding the value of not making the
InstructionLoaderinstantiate the hashmap and text utils while still making this testable. It's basically acting as a dependency injection utility method