“這是我參與8月更文挑戰的第19天,活動詳情檢視: 8月更文挑戰” juejin.cn/post/698796…
小菜嘗試做一個積分進度和類似物流進度的小元件,優先考慮的是自定義 ListView 但還是查閱了一下資料,發現神奇的 Stepper 步進器,雖不能完全滿足需求,但提供了很好的思路,小菜僅就基本的 Stepper 學習一下;
原始碼分析
const Stepper({
Key key,
@required this.steps, // Step 列表
this.physics, // 滑動動畫
this.type = StepperType.vertical, // 方向:橫向/縱向
this.currentStep = 0, // 當前所在 Step
this.onStepTapped, // Step 點選回撥
this.onStepContinue, // Step 繼續按鈕回撥
this.onStepCancel, // Step 取消按鈕回撥
this.controlsBuilder, // 自定義控制元件
})
class Step
const Step({
@required this.title, // 標題
this.subtitle, // 副標題
@required this.content, // 內容
this.state = StepState.indexed, // 狀態
this.isActive = false, // 是否高亮
})
}
複製程式碼
分析原始碼可知,Stepper 中存放的是 Step 列表,且 Step 數量不可變,其中包括了點選的回撥等;Step 只是一個類而非 Widget 故不能單獨使用;
案例嘗試
Step
- title 為描述性標題;content 為標題與副標題之下的內容,預設包含 continue 和 cancel 按鈕;兩者均為 Widget 且不可為 null;
return Stepper(steps: [
Step(title: Text('Step 標題一'), content: Container(color: Colors.orangeAccent.withOpacity(0.4), child: Text('Step 內容一'))),
Step(title: Text('Step 標題二'), content: Container(color: Colors.blueAccent.withOpacity(0.4), child: Text('Step 內容二'))),
Step(title: Text('Step 標題三'), content: Container(color: Colors.purple.withOpacity(0.4), child: Text('Step 內容三')))
]);
複製程式碼
- subtitle 為副標題,在 title 之下,預設小一個字號;
return Stepper(steps: [
Step(title: Text('Step 標題一'), subtitle: Text('Step 副標題一'),
content: Container(color: Colors.orangeAccent.withOpacity(0.4), child: Text('Step 內容一'))),
Step(title: Text('Step 標題二'), subtitle: Text('Step 副標題二'),
content: Container(color: Colors.blueAccent.withOpacity(0.4), child: Text('Step 內容二'))),
Step(title: Text('Step 標題三'), subtitle: Text('Step 副標題三'),
content: Container(color: Colors.purple.withOpacity(0.4), child: Text('Step 內容三')))
]);
複製程式碼
- state 為狀態,Flutter 預設提供了多種狀態樣式;
a. indexed: 在圓中展示每個 Step 陣列下標(從 1 開始); b. editing: 編輯狀態,在圓中展示鉛筆圖示; c. complete: 完成狀態,在圓中展示刻度圖示; d. disabled: 不可用狀態,為灰色; e. error: 錯誤狀態,在紅色三角中展示歎號圖示;
return Stepper(steps: [
Step(title: Text('Step state -> indexed'), state: StepState.indexed, content: Container()),
Step(title: Text('Step state -> editing'), state: StepState.editing, content: Container()),
Step(title: Text('Step state -> complete'), state: StepState.complete, content: Container()),
Step(title: Text('Step state -> disabled'), state: StepState.disabled, content: Container()),
Step(title: Text('Step state -> error'), state: StepState.error, content: Container())
]);
複製程式碼
- isActive 為設定當前 Step 是否高亮,僅圖示高亮,其中 error 狀態預設高亮,disabled 狀態圖示也可高亮;
return Stepper(steps: [
Step(isActive: true, title: Text('Step state -> indexed'), state: StepState.indexed, content: Container()),
Step(isActive: true, title: Text('Step state -> editing'), state: StepState.editing, content: Container()),
Step(isActive: true, title: Text('Step state -> complete'), state: StepState.complete, content: Container()),
Step(isActive: true, title: Text('Step state -> disabled'), state: StepState.disabled, content: Container()),
Step(isActive: true, title: Text('Step state -> error'), state: StepState.error, content: Container())
]);
複製程式碼
Stepper
- type 包括橫向 horizontal 展示與縱向 vertical 展示兩類,預設是 vertical;
return Stepper(type: StepperType.horizontal,
steps: [
Step(title: Text('Step 標題一'), content: Container()),
Step(title: Text('Step 標題二'), content: Container()),
Step(title: Text('Step 標題三'), content: Container())
]);
複製程式碼
- currentStep 為當前 Step,注意陣列下標從 0 開始;
return Stepper(type: StepperType.horizontal, currentStep: 1,
steps: [
Step(title: Text('Step 標題一'), content: Container(child: Text('Step 內容一'))),
Step(title: Text('Step 標題二'), content: Container(child: Text('Step 內容二'))),
Step(title: Text('Step 標題三'), content: Container(child: Text('Step 內容三')))
]);
複製程式碼
- onStepTapped 為 Step 點選回撥,小菜嘗試點選切換 Step 時獲取當前 Step 高亮;
var _curStep = 0;
return Stepper(currentStep: _curStep,
onStepTapped: (step) { setState(() { _curStep = step; }); },
steps: [
Step(title: Text('Step 標題一'), content: Container(child: Text('Step 內容一')), isActive: _curStep >= 0 ? true : false),
Step(title: Text('Step 標題二'), content: Container(child: Text('Step 內容二')), isActive: _curStep >= 1 ? true : false),
Step(title: Text('Step 標題三'), content: Container(child: Text('Step 內容三')), isActive: _curStep >= 2 ? true : false)
]);
複製程式碼
- onStepContinue 為 Step 中繼續按鈕點選回撥;**** 為 Step 中取消按鈕點選回撥;小菜嘗試對繼續和取消點選進行 Step 切換;
return Stepper(currentStep: _curStep,
onStepTapped: (step) { setState(() { _curStep = step; }); },
onStepContinue: () { setState(() { if (_curStep < 2) { _curStep++; } }); },
onStepCancel: () { setState(() { if (_curStep > 0) { _curStep--; } }); },
steps: [
Step(title: Text('Step 標題一'), content: Container(child: Text('Step 內容一')), isActive: _curStep >= 0 ? true : false),
Step(title: Text('Step 標題二'), content: Container(child: Text('Step 內容二')), isActive: _curStep >= 1 ? true : false),
Step(title: Text('Step 標題三'), content: Container(child: Text('Step 內容三')), isActive: _curStep >= 2 ? true : false)
]);
複製程式碼
- controlsBuilder 用來自定義繼續和取消按鈕,若不需要展示則設定空 Widget 即可;
return Stepper(currentStep: _curStep,
onStepTapped: (step) { setState(() { _curStep = step; }); },
onStepContinue: () { setState(() { if (_curStep < 2) { _curStep++; } }); },
onStepCancel: () { setState(() { if (_curStep > 0) { _curStep--; } }); },
controlsBuilder: (BuildContext context, {VoidCallback onStepContinue, VoidCallback onStepCancel}) {
return Row(children: <Widget>[
Container( width: 100,
child: Image.asset(_curStep == 0 ? 'images/icon_hzw01.jpg' : _curStep == 1 ? 'images/icon_hzw02.jpg' : 'images/icon_hzw03.jpg')),
SizedBox(width: 30, height: 30),
Column(children: <Widget>[
FlatButton(color: Colors.orangeAccent.withOpacity(0.4), onPressed: onStepContinue, child: Text('下一步')),
FlatButton(color: Colors.purple.withOpacity(0.4), onPressed: onStepCancel, child: Text('上一步'))
])
]);
},
steps: [
Step(title: Text('Step 標題一'), content: Container(child: Text('Step 內容一')), isActive: _curStep >= 0 ? true : false),
Step(title: Text('Step 標題二'), content: Container(child: Text('Step 內容二')), isActive: _curStep >= 1 ? true : false),
Step(title: Text('Step 標題三'), content: Container(child: Text('Step 內容三')), isActive: _curStep >= 2 ? true : false)
]);
複製程式碼
- physics 為滑動屬性,小菜測試將 Stepper 放在 ListView 中且不能完全展示時,設定 ClampingScrollPhysics() 可連續滑動;
physics: ClampingScrollPhysics(),
複製程式碼
Stepper 使用方便快捷,雖樣式相對固定無法滿足所有需求,但給我們提供了很好的自定義思路;小菜對 Stepper 研究尚淺,如有錯誤請多多指導!
來源: 阿策小和尚