我是新来的人。我正在尝试实现此用户界面
我还没有发现使用完整的解决方案来在flutter中创建透明的底部导航栏。
我尝试使用
BottomNavigationBarItem(
backgroundColor: Colors.transparent,
icon: e,
activeIcon: _activeIcons[_index],
title: Text(
title[_index],
style: AppStyle.tabBarItem,
),
)
但这似乎不起作用。请帮忙。
答案 0 :(得分:3)
这就是我实现这一目标的方式
return Scaffold(
body: Builder(
builder: (context) => Container(
decoration: bgAuthenticationDecoration(),
child: _HomeBodyWidget(_currentIndex),
),
),
bottomNavigationBar: BottomNavigationBar(items: <BottomNavigationBarItem>[
BottomNavigationBarItem(icon: Icon(Icons.home,),title: Container()),
BottomNavigationBarItem(icon: Icon(Icons.message),title: Container()),
BottomNavigationBarItem(icon: Icon(Icons.list),title: Container()),
BottomNavigationBarItem(icon: Icon(Icons.favorite),title: Container()),
BottomNavigationBarItem(icon: Icon(Icons.supervised_user_circle),title: Container()),
],
backgroundColor:Colors.black.withOpacity(0.1),),
extendBodyBehindAppBar: true,
extendBody: true,
);
然后,您必须在应用程序主题中将画布颜色设置为透明。
canvasColor: Colors.transparent
希望这会有所帮助。
祝您编程愉快!
答案 1 :(得分:3)
给出的答案中的任何一个都不对我有用,我发现很重要的一点:您必须添加属性extendBody: true
如果为true,并且指定了bottomNavigationBar或persistentFooterButtons,则然后主体将扩展到脚手架的底部,而不是仅扩展到bottomNavigationBar或persistentFooterButtons的顶部。
当bottomNavigationBar具有非矩形形状(例如CircularNotchedRectangle)时,此属性通常很有用,该形状会在条的顶部边缘添加FloatingActionButton大小的槽口。在这种情况下,指定extendBody:true可确保通过底部导航栏的槽口可见支架的身体
连同backgroundColor: Color(0x00ffffff),
。
NB:0x的颜色是十六进制的ARGB值(0xAARRGGBB),因此ffffff之前的00表示最大的透明度,您可以通过将00增加到ff(十六进制的255)来增加不透明度。
完整代码示例:
import 'package:flutter/material.dart';
class NavigationBar extends StatefulWidget {
static int _selectedIndex = 0;
@override
NavigationBarState createState() => NavigationBarState();
}
class NavigationBarState extends State<NavigationBar> {
void _onItemTapped(int index) {
setState(() {
NavigationBar._selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return BottomNavigationBar(
currentIndex: NavigationBar._selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
backgroundColor: Color(0x00ffffff), // transparent
type: BottomNavigationBarType.fixed,
unselectedItemColor: Colors.blue,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Home'),
),
BottomNavigationBarItem(
icon: Icon(Icons.grade),
title: Text('Level'),
),
BottomNavigationBarItem(
icon: Icon(Icons.notifications),
title: Text('Notification'),
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
title: Text('Achievments'),
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
title: Text('Settings'),
),
]
);
}
@override
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
}
然后在其中让MaterialApp返回:
return MaterialApp(
home: Scaffold(
extendBody: true, // very important as noted
bottomNavigationBar: NavigationBar, // here you make use of the transparent bar.
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: ExactAssetImage("assets/background.png"), // because if you want a transparent navigation bar I assume that you have either a background image or a background color.
fit: BoxFit.fill
),
),
child: Container(
// the body of your app
),
),
),
);
}
}
我希望这会有所帮助。
答案 2 :(得分:2)
我尝试使用注释中讨论的Stack方法:
<xsl:for-each select="/Documents/Document/Invoice/Tables/Table/TableRow">
<cac:InvoiceLine>
<cbc:InvoicedQuantity>
<xsl:value-of select="Field[@Type='LIT_DeliveredQuantity']"/>
</cbc:InvoicedQuantity>
<xsl:for-each select="../../../Fields/Field[@Type='BTWverlegd' and @TextDetail='AE']">
<cac:TaxTotal>
<cac:TaxSubtotal>
<cbc:TaxableAmount>
<xsl:for-each select="/Documents/Document/Invoice/Tables/Table/TableRow">
<xsl:value-of select="/Documents/Document/Invoice/Tables/Table/TableRow/Field[@Type='LIT_VatExcludedAmount']"/>
</xsl:for-each>
</cbc:TaxableAmount>
</cac:TaxSubtotal>
</cac:TaxTotal>
</xsl:for-each>
</cac:InvoiceLine>
</xsl:for-each>
编辑:<Invoice>
<cac:InvoiceLine>
<cbc:InvoicedQuantity>3.00</cbc:InvoicedQuantity>
<cac:TaxTotal>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="EUR">6.75</cbc:TaxableAmount>
</cac:TaxSubtotal>
</cac:TaxTotal>
</cac:InvoiceLine>
<cac:InvoiceLine>
<cac:TaxTotal>
<cbc:InvoicedQuantity>5.00</cbc:InvoicedQuantity>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="EUR">140.00</cbc:TaxableAmount>
</cac:TaxSubtotal>
</cac:TaxTotal>
</cac:InvoiceLine>
<cac:InvoiceLine>
<cbc:ID/>
<cbc:InvoicedQuantity>7.00</cbc:InvoicedQuantity>
<cac:TaxTotal>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="EUR">108.50</cbc:TaxableAmount>
</cac:TaxSubtotal>
</cac:TaxTotal>
</cac:InvoiceLine>
</Invoice>
具有 Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/background.jpg'),
fit: BoxFit.cover),
),
),
Align(
alignment: Alignment.bottomCenter,
child: Theme(
data: Theme.of(context)
.copyWith(canvasColor: Colors.transparent),
child: BottomNavigationBar(
currentIndex: 0,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home), title: Text('Home')),
BottomNavigationBarItem(
icon: Icon(Icons.home), title: Text('Home')),
BottomNavigationBarItem(
icon: Icon(Icons.home), title: Text('Home'))
],
))),
],
),
),
);
}
的内置标高,您无法更改它,并造成了怪异的阴影效果。如果要删除它,可以像这样实现自己的底部栏:
BottomNavigationBar
答案 3 :(得分:1)
这是我的方法:
Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.fill,
image: NetworkImage("https://cdn.pixabay.com/photo/2018/09/17/16/24/cat-3684184_960_720.jpg")
)
),
),
Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Theme(
data: Theme.of(context).copyWith(canvasColor: Colors.transparent),
child: BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: Icon(Icons.photo_camera), title: Text("Test")),
BottomNavigationBarItem(
icon: Icon(Icons.photo_camera), title: Text("Test")),
],
),
)
],
)
],
);
这将用背景图像(底部层)和位于内容与end
对齐的列内的底部导航栏填充整个屏幕(图像纯属琐碎,但您会得到东西)。
出于完成目的,我将在给出的解释下粘贴到原始问题的评论中。
更深入地思考,我意识到这将不一样 所需的结果,因为两个女孩的形象将高于 导航栏。我建议对两个女孩图像使用堆栈 作为底层(堆栈的底部)和全屏列 将MainAxisSize设置为MainAxisSize.max并将MainAxisAlignment设置为 MainAxisAlignment.end。我可以在答案中写出来,但我无法测试 现在,所以我宁愿写评论。希望对您有帮助
更新
先前的解决方案仍然具有导航栏阴影。
屏幕的这种构建方法(小部件)没有,因为我已经用BottomNavigationBar
实现了自己的Row
:
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.fill,
image: NetworkImage(
"https://media.idownloadblog.com/wp-content/uploads/2016/04/macinmac-portrat-splash.jpg"))),
),
Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
GestureDetector(
onTap: () {
print("Tap!");
},
child: Icon(
Icons.photo_camera,
size: 50,
)),
GestureDetector(
onTap: () {
print("Tap!");
},
child: Icon(
Icons.photo_camera,
size: 50,
)),
GestureDetector(
onTap: () {
print("Tap!");
},
child: Icon(
Icons.photo_camera,
size: 50,
)),
GestureDetector(
onTap: () {
print("Tap!");
},
child: Icon(
Icons.photo_camera,
size: 50,
)),
],
)
],
)
],
);
这是我手机上的屏幕截图:
奖金
您可以通过致电实现全屏显示
SystemChrome.setEnabledSystemUIOverlays([]);
来源:here
答案 4 :(得分:0)
我的高级解决方案:
'use strict';
const Hapi = require('hapi');
const Basic = require('hapi-auth-basic');
const server = new Hapi.Server();
server.connection({
port: 2090,
host: 'localhost'
});
var vorpal = require('vorpal')();
const chalk = vorpal.chalk;
var fs = require("fs");
var utenti = [{
name: 'a',
pass: 'b'
},
{
name: 'c',
pass: 'd'
}
];
const users = {
john: {
username: 'john',
password: 'secret',
name: 'John Doe',
id: '2133d32a'
},
paul: {
username: 'paul',
password: 'password',
name: 'Paul Newman',
id: '2133d32b'
}
};
var messaggi = [{
destinazione: 'a',
sorgente: 'c',
messsaggio: 'ciao'
},
{
destinazione: 'a',
sorgente: 'c',
messsaggio: 'addio'
},
{
destinazione: 'c',
sorgente: 'a',
messsaggio: 'arrivederci'
}
];
var login = '';
var loggato = false;
vorpal
.command('login <name> <pass>')
.description('Effettua il login al sistema')
.action(function (args, callback) {
loggato = false;
utenti.forEach(element => {
if ((element.name == args.name) && (element.pass == args.pass)) {
loggato = true;
login = args.name;
console.log("Accesso effettuato");
}
});
if (!loggato)
console.log("Login e Password errati");
callback();
});
vorpal
.command('leggi')
.description('Leggi i messaggi ricevuti')
.action(function (args, callback) {
if (loggato) {
var estratti = messaggi.filter(function (element) {
return element.destinazione == login;
});
estratti.forEach(element => {
console.log("mittente : " + element.sorgente);
console.log(chalk.red(element.messsaggio));
});
} else {
console.log("Devi prima loggarti");
}
callback();
});
vorpal
.command('invia <dest> "<messaggio>"')
.description('Invia un messaggio ad un altro utente')
.action(function (args, callback) {
if (loggato) {
var trovato = utenti.find(function (element) {
return element.name == args.dest;
});
if (trovato != undefined) {
messaggi.push({
destinazione: args.dest,
sorgente: login,
messsaggio: args.messaggio
});
console.log(messaggi);
}
} else {
console.log("Devi prima loggarti");
}
callback();
});
vorpal
.command('crea <login> <pass>')
.description('Crea un nuovo utente')
.action(function (args, callback) {
var trovato = utenti.find(function (element) {
return element.name == args.login;
});
if (trovato == undefined) {
utenti.push({
name: args.login,
pass: args.pass
});
console.log(utenti);
}
callback();
});
vorpal
.command('file leggi utenti')
.description('Legge il file utenti')
.action(function (args, callback) {
var contents = fs.readFileSync("utenti.json");
utenti = JSON.parse(contents);
callback();
});
vorpal
.command('file scrivi utenti')
.description('Scrive il file utenti')
.action(function (args, callback) {
var jsontostring = JSON.stringify(utenti);
fs.writeFile('utenti.json', jsontostring, function (err) {
if (err) {
return console.error(err);
}
});
callback();
});
vorpal
.command('file leggi messaggi')
.description('Legge il file messaggi')
.action(function (args, callback) {
var contents = fs.readFileSync("messaggi.json");
messaggi = JSON.parse(contents);
callback();
});
vorpal
.command('file scrivi messaggi')
.description('Scrive il file messaggi')
.action(function (args, callback) {
var jsontostring = JSON.stringify(messaggi);
fs.writeFile('messaggi.json', jsontostring, function (err) {
if (err) {
return console.error(err);
}
});
callback();
});
// leggi file , scrivi file
vorpal
.delimiter(chalk.yellow('messaggi$'))
.show();
const validate = function (request, username, password, callback) {
loggato = false;
utenti.forEach(element => {
if ((element.name == username) && (element.pass == password)) {
loggato = true;
console.log("Accesso effettuato");
return callback(null, true, {
name: username
})
}
});
if (!loggato)
return callback(null, false);
};
server.register(Basic, function (err) {
if (err) {
throw err;
}
});
server.auth.strategy('simple', 'basic', {
validateFunc: validate
});
server.route({
method: 'GET',
path: '/',
config: {
auth: 'simple',
handler: function (request, reply) {
reply('hello, ' + request.auth.credentials.name);
}
}
});
//route scrivere
server.route({
method: 'POST',
path: '/invia',
config: {
auth: 'simple',
handler: function (request, reply) {
//console.log("Received POST from " + request.payload.name + "; id=" + (request.payload.id || 'anon'));
var payload = encodeURIComponent(request.payload)
console.log(request.payload);
console.log(request.payload.dest);
console.log(request.payload.messaggio);
messaggi.push({
destinazione: request.payload.dest,
sorgente: request.auth.credentials.name,
messsaggio: request.payload.messaggio
});
var jsontostring = JSON.stringify(messaggi);
fs.writeFile('messaggi.json', jsontostring, function (err) {
if (err) {
return console.error(err);
}
});
console.log(messaggi);
reply(messaggi[messaggi.length - 1]);
}
}
});
//route leggere (json)
server.route({
method: 'GET',
path: '/messaggi',
config: {
auth: 'simple',
handler: function (request, reply) {
messaggi = fs.readFileSync("messaggi.json");
var estratti = messaggi.filter(function (element) {
return element.destinazione == request.auth.credentials.name;
});
var s = [];
console.log(request.auth.credentials.name);
console.log(estratti.length);
estratti.forEach(element => {
s.push(element);
//fare l'array con stringify
//s+="mittente : "+element.sorgente+": "+element.messsaggio+"\n";
});
var a = JSON.stringify(s);
console.log(a);
console.log(s);
reply(a);
}
}
});
server.start(function () {
console.log('Hapi is listening to ' + server.info.uri);
});
function EseguiSql(connection, sql, reply) {
var rows = [];
request = new Request(sql, function (err, rowCount) {
if (err) {
console.log(err);
} else {
console.log(rowCount + ' rows');
console.log("Invio Reply")
reply(rows);
}
});
request.on('row', function (columns) {
var row = {};
columns.forEach(function (column) {
row[column.metadata.colName] = column.value;
});
rows.push(row);
});
connection.execSql(request);
}
server.route({
method: 'POST',
path: '/query',
handler: function (request, reply) {
// Qui dovrebbe cercare i dati nel body e rispondere con la query eseguita
var connection = new Connection(config);
// Attempt to connect and execute queries if connection goes through
connection.on('connect', function (err) {
if (err) {
console.log(err);
} else {
console.log('Connected');
console.log(request.payload.sql);
EseguiSql(connection, request.payload.sql, reply);
}
});
}
});
server.connection({
host: process.env.HOST || 'localhost',
port: process.env.PORT || 8080
});
var config = {
userName: process.env.DB_USER,
password: process.env.DB_PASSWORD,
server: process.env.DB_SERVER,
options: {
database: process.env.DB_NAME,
encrypt: true
}
}
这个想法是一个堆栈,其底部具有可滚动的视图,顶部具有对齐的自定义底部栏
答案 5 :(得分:0)
在新版本的flutter(1.2.1)中,有一个用于海拔的参数,您可以将 海拔:0.0
答案 6 :(得分:0)
您可以做类似...
不要忘记设置elevation: 0
并使用导入
import 'package:flutter/services.dart';
隐藏状态栏
void main() {
SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]);
runApp(MaterialApp(
home: MyApp()));
}
BottomNavigationBar透明
BottomNavigationBar(
backgroundColor: Colors.black.withOpacity(0.1), //here set your transparent level
elevation: 0,
);
这是完整的代码
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
Container(
child: Image.network("https://picsum.photos/660/1420"),
),
Align(
alignment: Alignment.bottomCenter,
child: BottomNavigationBar(
backgroundColor: Colors.black.withOpacity(0.1), //here set your transparent level
elevation: 0,
selectedItemColor: Colors.blueAccent,
unselectedItemColor: Colors.white,
type: BottomNavigationBarType.fixed,
currentIndex: 0,
showSelectedLabels: false,
showUnselectedLabels: false,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.notifications_none, size: 30), title: Text('Notifications')),
BottomNavigationBarItem(
icon: Icon(Icons.search, size: 30), title: Text('Search')),
BottomNavigationBarItem(
icon: Icon(Icons.perm_identity, size: 30), title: Text('User'))
],
)),
],
),
);
}
答案 7 :(得分:0)
Scaffold(
floatingActionButton: _buildTransparentButton()
)
您可以尝试浮动操作按钮。
答案 8 :(得分:-2)
找到了透明BottomNavigationBar
的解决方案。
BottomNavigationBar
的源代码。Widget build
的方法。Stack widget
,您可以在其中找到一个材质小部件。shadowColor:Colors.transparent
现在您可以获得透明的BottomNavigationBar