问题
According to Google's new Material Design guidelines, the navigation bar is supposed to be at the bottom. How can I implement it (if there is a way) ? For the moment, I'm using a Tabview which, by default on Android, is put at the top of the page. Thank you
回答1:
For this case, i created a custom Nativescript component. It's really basic but i hope it will help you.
- app/components/bottom-navigation.ts
import gridLayoutModule = require("ui/layouts/grid-layout");
import {Label} from "ui/label";
import dependencyObservableModule = require("ui/core/dependency-observable");
import {EventData} from "data/observable";
import frameModule = require("ui/frame");
export class BottomNavigation extends gridLayoutModule.GridLayout {
public static selectedItemProperty = new dependencyObservableModule.Property(
"selectedItem",
"BottomNavigation",
new dependencyObservableModule.PropertyMetadata(undefined, dependencyObservableModule.PropertyMetadataSettings.None,
function(data: dependencyObservableModule.PropertyChangeData) {
if (data.newValue) {
let instance = <BottomNavigation>data.object;
instance.setSelectedItem(data.newValue);
}
}));
public get selectedItem() {
return this._getValue(BottomNavigation.selectedItemProperty);
}
public set selectedItem(value: string) {
this._setValue(BottomNavigation.selectedItemProperty, value);
}
private _items = [
{ code: "TAB_1", icon: 0xe90a, label: "Tab 1" },
{ code: "TAB_2", icon: 0xe90b, label: "Tab 2"},
{ code: "TAB_3", icon: 0xe90c, label: "Tab 3"}];
constructor() {
super();
this.createUi();
}
public setSelectedItem(selectedItem: string) {
this.selectedItem = selectedItem;
let icon = this.getViewById(selectedItem + "_ICON");
icon.className = icon.className.replace("icon-unselected", "icon-selected");
let label = this.getViewById(selectedItem + "_LABEL");
label.className = "label-selected";
}
private createUi() {
this.removeChildren();
this.className = "bottom-navigation";
this.addColumn(new gridLayoutModule.ItemSpec(1, "star"));
this.addColumn(new gridLayoutModule.ItemSpec(1, "star"));
this.addColumn(new gridLayoutModule.ItemSpec(1, "star"));
for (let i = 0; i < this._items.length; i++) {
let currentItem = this._items[i];
let icon = new Label();
icon.id = currentItem.code + "_ICON";
icon.text = String.fromCharCode(currentItem.icon);
icon.className = "material-icon icon-unselected";
icon.on("tap", args => this.onNavigate(args, currentItem.code));
this.addChild(icon);
gridLayoutModule.GridLayout.setColumn(icon, i);
let label = new Label();
label.id = currentItem.code + "_LABEL";
label.text = currentItem.label;
label.className = "label-unselected";
label.on("tap", args => this.onNavigate(args, currentItem.code));
this.addChild(label);
gridLayoutModule.GridLayout.setColumn(label, i);
}
}
private onNavigate(args: EventData, code: string) {
let selectedLabel = <Label>args.object;
if (selectedLabel.className.indexOf("icon-selected") > -1) {
return;
}
let destinationUrl = "";
switch (code) {
case "TAB_1":
destinationUrl = "views/tab-1/tab-1";
break;
case "TAB_2":
destinationUrl = "views/tab-2/tab-2";
break;
case "TAB_3":
destinationUrl = "views/tab-3/tab-3";
break;
}
frameModule.topmost().navigate({
animated: false,
backstackVisible: false,
moduleName: destinationUrl
});
}
}
- my-view.xml
<Page xmlns="http://schemas.nativescript.org/tns.xsd"
xmlns:bn="components/bottom-navigation">
<GridLayout rows="*, auto">
<GridLayout>
<!-- Your view here -->
</GridLayout>
<bn:BottomNavigation row="1" selectedItem="TAB_1" />
</GridLayout>
</Page>
EDIT : Here is the associated SASS style
.bottom-navigation {
background-color: $primary-color;
height: 56;
color: $primary-color-text;
.icon {
horizontal-align: center;
font-size:46;
}
.icon-selected {
@extend .icon;
}
.icon-unselected {
@extend .icon;
vertical-align: center;
}
.label {
horizontal-align: center;
vertical-align: bottom;
margin-bottom: 4;
}
.label-unselected {
@extend .label;
visibility: collapse;
}
.label-selected {
@extend .label;
visibility: visible;
}
}
回答2:
As of right now there isn't a shipped widget from Google. So you have to roll your own. There are several open source implementations of the component spec.
One of the better ones I have found that you could use with NativeScript is, https://github.com/roughike/BottomBar
Another alternative is to use a grid-layout
pinned to the bottom of you view, set the navigation bar to be transparent, this is covered in my blog post here. Then you could use the nativescript animation API to animate the labels for the effect. You would then use this :http://developer.android.com/reference/android/view/ViewAnimationUtils.html#createCircularReveal(android.view.View, int, int, float, float) to animate the circular reveal effect.
I might write up a post using already available NativeScript and then if I have time make that library into a plugin for NativeScript
I put this together in a few minutes yesterday using a library for the Bottom Bar.
回答3:
This might not be the perfect solution but, Since you should use viewpager in this case. Put gravity of the parent linear layout to bottom. The tab automatically moves to bottom of the page.
Hope this helps thanks!!!
来源:https://stackoverflow.com/questions/36567491/nativescript-android-new-navigation-bar