Flutter?頁面跳轉(zhuǎn)和傳值的實現(xiàn)
一、頁面跳轉(zhuǎn)
1.基本頁面跳轉(zhuǎn)
Navigator 介紹
在 Flutter 中,Navigator 是一個管理應(yīng)用視圖(頁面)的組件,它使用棧(Stack)的方式來控制頁面的切換。每當(dāng)你跳轉(zhuǎn)到一個新頁面時,Navigator 會將新頁面的 Route 壓棧(push),當(dāng)你返回到之前的頁面時,它會將當(dāng)前頁面的 Route 出棧(pop)。
為了使用 Navigator 進行頁面跳轉(zhuǎn),我們需要使用 BuildContext,它表示當(dāng)前 widget 在 widget 樹中的位置。BuildContext 是用于與 Navigator 進行交互的必要參數(shù)。
Navigator.push 方法
Navigator.push 方法用于將新的 Route 壓入棧中,從而導(dǎo)航到新頁面。
Navigator.push( context, MaterialPageRoute(builder: (context) => NewPage()), );
或這種寫法
Navigator.push(context, MaterialPageRoute(
builder: (context) {
return NewPage();
},
));Navigator.pop 方法
Navigator.pop 方法用于將棧頂?shù)?nbsp;Route 彈出,返回到前一個頁面。
Navigator.pop(context);
MaterialPageRoute 和頁面跳轉(zhuǎn)動畫
MaterialPageRoute 是一種模態(tài)路由,它會根據(jù)目標(biāo)平臺的規(guī)范,為頁面切換提供適當(dāng)?shù)膭赢嫛T?Android 上,它通常是一個從屏幕底部向上滑入的動畫,而在 iOS 上,它通常是一個從屏幕右側(cè)滑入的動畫。
無參數(shù)頁面跳轉(zhuǎn)示例代碼
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: 'Navigation Basics',
home: HomePage(),
));
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home Page'),
),
body: Center(
child: ElevatedButton(
child: Text('Open New Page'),
onPressed: () {
// 使用 Navigator.push 方法來跳轉(zhuǎn)到新頁面
Navigator.push(
context,
MaterialPageRoute(builder: (context) => NewPage()),
);
},
),
),
);
}
}
class NewPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('New Page'),
),
body: Column(
children: [
Text('Welcome to the new page!'),
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text("pop"))
],
),
);
}
}2.命名路由和路由表
命名路由介紹
命名路由是一種用于管理頁面導(dǎo)航的技術(shù),它允許你為每個頁面分配一個唯一的名稱,并通過這些名稱在應(yīng)用程序中進行頁面之間的導(dǎo)航。命名路由,由一對字符串(路由名稱)和對應(yīng)的屏幕(或稱為頁面/視圖)組成。
命名路由的好處
- 提高代碼可維護性:命名路由使得路由和它們對應(yīng)的屏幕解耦,這讓查找和修改特定路由相關(guān)的代碼變得更加容易。
- 簡化路由管理:當(dāng)應(yīng)用的結(jié)構(gòu)變得更為復(fù)雜時,使用命名路由可以幫助集中管理路由,而不是在代碼中散布大量的
Navigator.push和MaterialPageRoute。
配置命名路由
我們可以在 MaterialApp 的 routes 屬性中定義所有的命名路由。routes 是一個 Map,它的鍵是字符串(路由的名稱),而值是對應(yīng)的構(gòu)造器函數(shù),返回相應(yīng)的頁面 Widget。
MaterialApp(
title: 'Navigation with Named Routes',
// 初始路由,應(yīng)用啟動時加載的路由
initialRoute: '/',
// 定義命名路由
routes: {
'/': (context) => HomePage(),
'/newPage': (context) => NewPage(),
'/thirdPage': (context) => ThirdPage(),
},
)
Navigator.pushNamed 方法
要使用命名路由進行頁面跳轉(zhuǎn),可以調(diào)用 Navigator.pushNamed 方法,并傳入對應(yīng)的路由名稱。
Navigator.pushNamed(context, '/newPage');
Navigator.pop 方法
Navigator.pop 方法用于將棧頂?shù)?nbsp;Route 彈出,返回到前一個頁面。
Navigator.pop(context);
Navigator.popAndPushNamed 方法
Navigator.popAndPushNamed 方法用于從當(dāng)前頁面返回到上一個頁面,并立即導(dǎo)航到指定的命名路由。
該方法的作用是先執(zhí)行 Navigator.pop 方法返回到上一個頁面,然后立即執(zhí)行 Navigator.pushNamed 方法導(dǎo)航到新的命名路由。
Navigator.popAndPushNamed(context, '/thirdPage');
配置和使用命名路由示例代碼
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: 'Navigation with Named Routes',
// 初始路由,應(yīng)用啟動時加載的路由
initialRoute: '/',
// 定義命名路由
routes: {
'/': (context) => HomePage(),
'/newPage': (context) => NewPage(),
'/thirdPage': (context) => ThirdPage(),
},
));
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home Page'),
),
body: Center(
child: ElevatedButton(
child: Text('Open New Page'),
// 使用命名路由進行頁面跳轉(zhuǎn)
onPressed: () {
Navigator.pushNamed(context, '/newPage');
},
),
),
);
}
}
class NewPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('New Page'),
),
body: Column(
children: [
Text('Welcome to the new page!'),
TextButton(
onPressed: () {
Navigator.popAndPushNamed(context, '/thirdPage');
},
child: Text("popAndPushNamed"))
],
),
);
}
}
class ThirdPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Third Page'),
),
body: Column(
children: [
Text('Welcome to the Third page!'),
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text("pop"))
],
),
);
}
}二、頁面?zhèn)髦?/h2>
1.push時向新頁面?zhèn)鬟f數(shù)據(jù)
(1).通過構(gòu)造函數(shù)傳遞數(shù)據(jù)
最直接的方式是通過目標(biāo)頁面的構(gòu)造函數(shù)直接傳遞數(shù)據(jù)。
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: HomePage(),
));
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home Page'),
),
body: Center(
child: ElevatedButton(
child: Text('Pass Data to New Page'),
onPressed: () {
// 通過構(gòu)造函數(shù)直接傳遞數(shù)據(jù)
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NewPage(data: 'Hello from Home Page!'),
),
);
},
),
),
);
}
}
class NewPage extends StatelessWidget {
final String data;
// 接收數(shù)據(jù)的構(gòu)造函數(shù)
NewPage({required this.data});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('New Page'),
),
body: Center(
child: Text(data), // 顯示傳遞過來的數(shù)據(jù)
),
);
}
}(2).使用 MaterialPageRoute 的 arguments 屬性
另一種傳遞數(shù)據(jù)的方式是使用 MaterialPageRoute 的 arguments 屬性,這在使用命名路由時尤其有用。
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
// 初始路由,應(yīng)用啟動時加載的路由
initialRoute: '/',
// 定義命名路由
routes: {
'/': (context) => HomePage(),
'/newPage': (context) => NewPage(),
},
));
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home Page'),
),
body: Center(
child: ElevatedButton(
child: Text('Pass Data to New Page'),
onPressed: () {
Navigator.pushNamed(
context,
'/newPage',
arguments: 'Hello from Home Page!',
);
},
),
),
);
}
}
class NewPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 獲取傳遞過來的數(shù)據(jù)
final String data = ModalRoute.of(context)!.settings.arguments as String;
return Scaffold(
appBar: AppBar(
title: Text('New Page'),
),
body: Center(
child: Text(data), // 顯示傳遞過來的數(shù)據(jù)
),
);
}
}2.pop時返回數(shù)據(jù)給前一個頁面
使用 Navigator.pop 返回結(jié)果
當(dāng)從一個頁面返回到前一個頁面時,可以通過 Navigator.pop 方法返回數(shù)據(jù):
// 假設(shè)這是 NewPage 中的一個按鈕,當(dāng)點擊時返回數(shù)據(jù)給前一個頁面
ElevatedButton(
onPressed: () {
Navigator.pop(context, 'Result from New Page');
},
child: Text('Return Data to Home Page'),
),Navigator.push 和 await 結(jié)合使用
你可以使用 await 關(guān)鍵字等待一個頁面返回結(jié)果:
// ... HomePage 中的按鈕點擊事件
onPressed: () async {
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => NewPage()),
);
// 使用 ScaffoldMessenger 顯示返回的結(jié)果
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(result?.toString() ?? 'No result')),
);
},或
onPressed: () async {
final result = await Navigator.pushNamed(
context,
'/newPage',
arguments: 'Hello from Home Page!',
);
// 使用 ScaffoldMessenger 顯示返回的結(jié)果
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(result?.toString() ?? 'No result')),
);
},
),使用 PopScope 攔截系統(tǒng)返回按鈕的行為
如果你不顯式的調(diào)用Navigator.pop(context, 'xxx'),就拿不到回傳結(jié)果。比如你從系統(tǒng)導(dǎo)航上點擊返回按鈕,就沒數(shù)據(jù)傳遞回去。
如果一定任何返回都回傳值,就需要定義導(dǎo)航欄,或者通過使用 PopScope widget 來攔截系統(tǒng)返回按鈕的行為,并執(zhí)行自定義的操作。
class NewPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('New Page'),
),
body: PopScope(
canPop: false, // 使用canPop提前禁用pop
onPopInvoked: (bool didPop) {
// canPop被設(shè)置為false時。didPop參數(shù)表示返回導(dǎo)航是否成功。
// `didPop`參數(shù)會告訴你路由是否成功地pop出
if (!didPop) {
// 在這里執(zhí)行你的操作,比如返回數(shù)據(jù). 前面不禁用pop的話,這里就會pop兩次了。
Navigator.pop(context, 'Custom back button result');
}
},
child: Column(
children: [
TextButton(
onPressed: () {
Navigator.pop(context, 'Result from New Page');
},
child: Text("pop"))
],
),
),
);
}
}注意:這里用多個地方調(diào)用Navigator.pop,從不同地方返回時,回傳的值也會不同。如果要求回傳的數(shù)據(jù)一致,就將Navigator.pop方法抽離放到一個方法中,多個返回位置調(diào)用同一個方法回傳同樣的數(shù)據(jù)。
三、路由生成鉤子(onGenerateRoute)
在Flutter中,onGenerateRoute是一個非常強大的鉤子,允許開發(fā)者對路由進行自定義操作。它在MaterialApp或CupertinoApp中定義,并在導(dǎo)航到命名路由時被調(diào)用,特別是當(dāng)使用Navigator.pushNamed時。它可以用于動態(tài)生成路由,傳遞參數(shù)到新頁面,甚至處理未知的路由。
下面是一個使用onGenerateRoute的示例,其中包括了處理動態(tài)路由和傳遞參數(shù)到未知頁面的代碼:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// 應(yīng)用初始路由
initialRoute: '/',
// onGenerateRoute 用于處理動態(tài)路由
onGenerateRoute: (RouteSettings settings) {
// 獲取傳遞過來的參數(shù),如果參數(shù)為null,則提供一個空的Map
final arguments = settings.arguments as Map<String, dynamic>? ?? {};
// 根據(jù) settings.name 處理不同路由
switch (settings.name) {
case '/':
return MaterialPageRoute(builder: (context) => HomePage());
case '/details':
// 假設(shè) DetailsPage 接受一個 'data' 參數(shù)
final String data = arguments['data'] as String? ?? '默認值';
return MaterialPageRoute(builder: (context) => DetailsPage(data: data));
default:
// 如果沒有匹配的路由,返回到一個未知頁面路由
return MaterialPageRoute(builder: (context) => UnknownPage());
}
},
);
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String _data = "缺省值";
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('首頁'),
),
body: Column(
children: [
Text(_data), // 顯示傳遞到本頁面的數(shù)據(jù)
ElevatedButton(
onPressed: () async {
// 導(dǎo)航到詳情頁,并傳遞數(shù)據(jù)。同時,使用await等待詳情頁返回的結(jié)果
final result = await Navigator.pushNamed(
context,
'/details',
arguments: {'data': '這是一個秘密信息!'},
);
final arguments = result as Map<String, dynamic>? ?? {};
setState(() {
if (mounted) {
_data = arguments["data"] as String? ?? "";
}
});
},
child: Text('前往詳情頁'),
),
],
),
);
}
}
class DetailsPage extends StatelessWidget {
final String data;
DetailsPage({required this.data});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('詳情頁'),
),
body: Column(
children: [
Text(data), // 顯示傳遞到本頁面的數(shù)據(jù)
TextButton(
onPressed: () {
// 回傳數(shù)據(jù)數(shù)據(jù)
Navigator.pop(context, {'data': '詳情返回數(shù)據(jù)'});
},
child: Text("pop"))
],
),
);
}
}
class UnknownPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('未知頁面'),
),
body: Center(
child: Text('該路由名稱不存在。'),
),
);
}
}四、路由傳值的安全性
1.驗證傳入數(shù)據(jù)
當(dāng)通過路由傳遞數(shù)據(jù)時,重要的是要驗證接收的數(shù)據(jù)是否符合預(yù)期。你可以使用類型檢查、正則表達式或自定義驗證函數(shù)來確保數(shù)據(jù)的有效性和安全性。
bool isValidData(dynamic data) {
// 在這里添加驗證邏輯,例如類型檢查、內(nèi)容檢查等
return data is String && data.isNotEmpty;
}在使用數(shù)據(jù)之前,你可以調(diào)用這個函數(shù)來驗證:
if (isValidData(receivedData)) {
// 數(shù)據(jù)有效,可以安全使用
} else {
// 數(shù)據(jù)無效,可以拋出異?;蜻M行錯誤處理
}2.處理空值和異常
處理空值和異常是確保應(yīng)用程序穩(wěn)定性的重要部分。當(dāng)你從路由接收數(shù)據(jù)時,應(yīng)該始終假設(shè)這些數(shù)據(jù)可能為空或者不是預(yù)期的格式。下面是一些處理這些情況的策略:
處理空值
當(dāng)你期望的數(shù)據(jù)可能為空時,可以使用Dart的null-aware運算符來優(yōu)雅地處理:
String data = receivedData ?? '默認值';
或者在使用之前檢查數(shù)據(jù)是否為null:
if (receivedData != null) {
// 使用 receivedData
} else {
// 處理空值情況,例如返回錯誤提示或設(shè)置默認值
}異常處理
如果數(shù)據(jù)轉(zhuǎn)換或驗證過程中可能拋出異常,你應(yīng)該使用try-catch語句來捕獲這些異常:
try {
// 嘗試使用 receivedData
} catch (e) {
// 處理異常,例如記錄日志、顯示錯誤信息等
}五、使用 Provider 管理跨頁面的狀態(tài)
Provider 是一個流行的狀態(tài)管理庫,它依賴于 Flutter 的 InheritedWidget 來向下傳遞數(shù)據(jù)。它能夠讓你在 widget 樹中跨越多個層級來傳遞和修改數(shù)據(jù),而無需手動傳遞回調(diào)或數(shù)據(jù)。
使用 Provider,你可以在應(yīng)用的頂層提供一個狀態(tài),然后在應(yīng)用的任何其他部分訪問或修改這個狀態(tài)。這適用于跨多個頁面?zhèn)鬟f數(shù)據(jù),甚至是整個應(yīng)用的狀態(tài)管理。
詳細使用參見另一文http://www.dbjr.com.cn/program/319047n8q.htm
1.使用 Provider 進行狀態(tài)管理和傳值
首先,你需要在 pubspec.yaml 文件中添加 provider 依賴項:
dependencies:
flutter:
sdk: flutter
provider: ^6.1.2 # 使用適合你的版本然后,在應(yīng)用頂層(即要包裹住MaterialApp)引入 Provider:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(
// 通過 MultiProvider 可以提供多個對象
MultiProvider(
providers: [
// ChangeNotifierProvider 是 Provider 的一種,它可以響應(yīng)通知
ChangeNotifierProvider(create: (context) => DataProvider()),
],
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: HomePage(),
);
}
}// 定義一個繼承自 ChangeNotifier 的數(shù)據(jù)模型,用來傳遞和響應(yīng)變化
class DataProvider extends ChangeNotifier {
String _data = "初始數(shù)據(jù)";
String get data => _data;
void setData(String newData) {
_data = newData;
notifyListeners(); // 當(dāng)更新數(shù)據(jù)時,通知監(jiān)聽的 widgets 進行重建
}
}HomePage 中的按鈕點擊時,可以使用 Provider 來更新數(shù)據(jù):
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 使用 Provider.of 來獲取最近的 DataProvider 實例
final dataProvider = Provider.of<DataProvider>(context);
return Scaffold(
appBar: AppBar(
title: Text('首頁'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
// 更新數(shù)據(jù)
dataProvider.setData('更新的數(shù)據(jù)');
// 導(dǎo)航到詳情頁
Navigator.push(
context,
MaterialPageRoute(builder: (context) => DetailsPage()),
);
},
child: Text('前往詳情頁并傳遞數(shù)據(jù)'),
),
),
);
}
}
class DetailsPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 監(jiān)聽 DataProvider,當(dāng)數(shù)據(jù)變化時重建這個 widget
final data = Provider.of<DataProvider>(context).data;
return Scaffold(
appBar: AppBar(
title: Text('詳情頁'),
),
body: Center(
// 顯示從 Provider 獲取的數(shù)據(jù)
child: Text(data),
),
);
}
}2.完整的Provider例子
下面是一個使用Provider進行狀態(tài)管理和跨頁面?zhèn)髦档耐暾纠?,包括異常處理和空值檢查:
首先,確保已經(jīng)添加了provider依賴。
// main.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<DataModel>(
create: (_) => DataModel(),
child: MaterialApp(
title: 'Flutter Demo',
home: HomePage(),
),
);
}
}
class DataModel extends ChangeNotifier {
String _data = '';
String get data => _data;
void updateData(String newData) {
if (newData.isNotEmpty) {
_data = newData;
notifyListeners();
} else {
throw Exception('Data cannot be empty');
}
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Home')),
body: Center(
child: Consumer<DataModel>(
builder: (context, dataModel, child) {
return ElevatedButton(
onPressed: () {
try {
dataModel.updateData('New Data from Home');
Navigator.push(
context,
MaterialPageRoute(builder: (context) => DetailsPage()),
);
} catch (e) {
// Handle the exception
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(e.toString())),
);
}
},
child: Text('Go to Details'),
);
},
),
),
);
}
}
class DetailsPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Details')),
body: Center(
child: Consumer<DataModel>(
builder: (context, dataModel, child) {
return Text(dataModel.data);
},
),
),
);
}
}在這個例子中,DataModel 是一個簡單的數(shù)據(jù)持有類,它通過Provider允許在應(yīng)用程序的其他部分訪問和修改數(shù)據(jù)。HomePage 設(shè)置新的數(shù)據(jù),并導(dǎo)航到DetailsPage。DetailsPage 顯示當(dāng)前的數(shù)據(jù)。如果嘗試設(shè)置空的數(shù)據(jù),DataModel 將拋出一個異常,該異常在HomePage中被捕獲并顯示為一個SnackBar。
到此這篇關(guān)于Flutter 頁面跳轉(zhuǎn)和傳值的實現(xiàn)的文章就介紹到這了,更多相關(guān)Flutter 頁面跳轉(zhuǎn)和傳值內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android?App應(yīng)用退到后臺顯示通知的實現(xiàn)方法
當(dāng)用戶收到app發(fā)過來的消息時,如果app沒有在前臺打開,需要提醒用戶有新的消息,所以這篇文章主要給大家介紹了關(guān)于Android?App應(yīng)用退到后臺顯示通知的實現(xiàn)方法,需要的朋友可以參考下2022-01-01
Android實現(xiàn)屏幕旋轉(zhuǎn)四個方向準確監(jiān)聽
這篇文章主要為大家詳細介紹了Android實現(xiàn)屏幕旋轉(zhuǎn)四個方向準確監(jiān)聽,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-07-07
Android應(yīng)用中使用ViewPager和ViewPager指示器來制作Tab標(biāo)簽
這篇文章主要介紹了Android中使用ViewPager和ViewPager指示器來制作Tab標(biāo)簽的方法,ViewPager指示器ViewPageIndicator是一個開源庫,文中舉了一個仿網(wǎng)易新聞客戶端Tab標(biāo)簽的例子,需要的朋友可以參考下2016-03-03
android判斷phonegap是否聯(lián)網(wǎng)且加載super.loadUrl網(wǎng)址
android判斷phonegap是否聯(lián)網(wǎng)動態(tài)加載super.loadUrl網(wǎng)址,接下來本文所提供的知識會幫助你解決以上問題,感興趣的你可不要錯過了哈2013-02-02
使用AccessibilityService實現(xiàn)微信自動切換賬號功能
這篇文章主要為大家詳細介紹了使用AccessibilityService實現(xiàn)微信自動切換賬號功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-12-12
Android GridView 滑動條設(shè)置一直顯示狀態(tài)(推薦)
這篇文章主要介紹了Android GridView 滑動條設(shè)置一直顯示狀態(tài)的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-12-12
Android ViewPager實現(xiàn)動畫切換效果
這篇文章主要為大家詳細介紹了Android ViewPager實現(xiàn)動畫切換效果的相關(guān)資料,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-01-01

