一緒に書く習慣をつけましょう!「ナゲッツデイリーニュープラン・4月アップデートチャレンジ」に参加して4日目です。クリックしてイベントの詳細をご覧ください。
たとえば、一部のページでは、連絡先や都市を選択するときに、必要なオプションをすばやく見つける必要があります。通常、WeChatアドレスブックの右側にあるナビゲーションバーのような機能が必要です。これはすばやく実行できます。 AからZまでの位置にあります。この記事この記事では、WeChatアドレスブックと同じ機能を自分たちで実装します。
- キーポイント:ジェスチャポジショニングスライディング、リストポジショニング、ジェスチャ、リストリンケージ。
データを準備するには、まずナビゲーションディレクトリデータを準備する必要があります。
List<String> _az = [
"☆",
"A", "B", "C", "D",
"E", "F", "G", "H",
"I", "G", "K", "L",
"M", "N", "O", "P",
"Q", "R", "S", "T",
"U", "V", "W", "X",
"Y", "Z",
];
复制代码
次に、リストデータ、リストデータを背景で並べ替えることができます。背景で並べ替えられない場合は、自分で並べ替えて組み立てることもできます。ここでは、プラグインを使用して、中国語に従ってピンインのイニシャルを取得します。文字、そして私たちは自分たちでこのデータを行うことができます。
lpinyin: ^2.0.3
复制代码
データ形式:NameBeanは文字のリストに対応します。これは、正式なリストデータを格納する形式です。
class NameBean {
String? initial;// 字母导航
List<Name>? nameList;// 内容列表
NameBean({
this.initial,
this.nameList,
});
}
/// name : "老李"
/// 这里我只放了一个name字段,以后扩展内容只需在这里新增字段就好了
class Name {
String? name;
Name({
this.name,
});
}
复制代码
次に、最初にナビゲーションバーを作成しましょう:
実装のアイデア:ナビゲーションバーはリストリストです。クリック、スライド、リリースの相互作用は異なります。さまざまな相互作用に従って実装します。ここでは、公式のGestureDetectorコンポーネントを使用します。ジェスチャ認識に使用されます。各アイテムの高さを修正し、ジェスチャの相互作用によって返される位置データを介して目的のディレクトリを返します。たとえば、各ディレクトリの高さは20に設定されています。
ナビゲーションバーコード:クリックまたは移動すると、選択したディレクトリにプレス効果があります。
GestureDetector(
child: Container(
margin: EdgeInsetsDirectional.only(top: 40),
width: 40,
// 导航条
child: ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (context, index) {
return SizedBox(
height: 20,
// 这里做了一个按压或移动滑动的触发效果
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color:
currentIndex == index ? Colors.redAccent : null,
shape: BoxShape.circle),
child: Text(
_az[index],
style: TextStyle(
color: currentIndex == index
? Colors.white
: Colors.black87,
),
),
),
);
},
itemCount: _az.length,
)),
//手指按下触发 竖着划就用onVertica XXX回调
onVerticalDragDown: (DragDownDetails e) {
//打印手指按下的位置(相对于屏幕)
int i = e.localPosition.dy ~/ 20;
// _scrollController.jumpTo(index: i);
setState(() {
currentIndex = i;
});
},
//手指滑动时会触发此回调
onVerticalDragUpdate: (DragUpdateDetails e) {
//用户手指滑动时,更新偏移
int i = e.localPosition.dy ~/ 20;
_az.length;
if (i >= 0 && i <= _az.length - 1) {
if (i != currentIndex) {
setState(() {
// 当前选中的index 默认-1
currentIndex = i;
});
print("滑动 ${_az[i]}");
}
}
},
// 手指抬起
onTapUp: (e) {
// 手指抬起
setState(() {
currentIndex = -1;
});
},
// 移动取消
onVerticalDragEnd: (e) {
// 移动取消
setState(() {
currentIndex = -1;
});
},
)
复制代码
次に、WeChatがスワイプしているときにジェスチャーで移動する文字拡大バブルがあることがわかります。
実装アイデア:バブルとナビゲーションバーを並べて、ジェスチャーの位置に応じて上マージンを更新できます。ナビゲーションバーの各アイテムの高さが固定されているため、スライド距離の高さを計算できます。スライド位置に応じた上部。ここのバブルは、UIに背景画像をカットさせることも、キャンバスを使用して自分で描画することもできます。
バブル描画のソースコード:現在、コンポーネントの描画を学んでいますが、ちなみに描画しました。最高ではないかもしれませんが、重要ではありません〜今日の焦点はそうではありません~~~
@override
void paint(Canvas canvas, Size size) {
// 原点移到左下角
canvas.translate(size.width / 2, size.height / 2);
Paint paint = Paint()
..color = Colors.redAccent
..strokeWidth = 2
..style = PaintingStyle.fill;
Path path = Path();
// 绘制文字
path.lineTo(0, -size.width / 2);
// path.conicTo(33, -28, 20, 0, 1);
path.arcToPoint(Offset(size.width / 2, 0),
radius: Radius.circular(size.width / 2),
largeArc: true,
clockwise: true);
path.close();
var bounds = path.getBounds();
canvas.save();
canvas.translate(-bounds.width / 2, bounds.height / 2);
canvas.rotate(pi * 1.2);
canvas.drawPath(path, paint);
canvas.restore();
// 绘制文字
var textPainter = TextPainter(
text: TextSpan(
text: text,
style: TextStyle(
fontSize: 24,
foreground: Paint()
..style = PaintingStyle.fill
..color = Colors.white,
)),
textAlign: TextAlign.center,
textDirection: TextDirection.ltr);
textPainter.layout();
canvas.translate(-size.width, -size.height / 2);
textPainter.paint(canvas, Offset(-size.width / 2.4, size.height / 1.2));
}
复制代码
ナビゲーションバーとバブルが完成しました。次のステップは非常に簡単です。ListViewを使用してコンテンツを入力することはできません。ここでは、公式のプラグインが必要です。scrollable_positioned_list: ^0.2.3
これを使用して特定のアイテムの位置を特定し、 listナビゲーションバーにリンクされています。
コンテンツコード:
ScrollablePositionedList.builder(
physics: BouncingScrollPhysics(),
itemScrollController: _scrollController,
itemBuilder: (context, index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: EdgeInsetsDirectional.only(start: 10),
child: Text(dataList[index].initial ?? ""),
color: Colors.grey.shade300,
height: 30,
width: double.infinity,
alignment: Alignment.centerLeft,
),
Container(
padding: EdgeInsetsDirectional.only(start: 15),
child: ListView.builder(
// 禁用滑动事件
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (context, cityIndex) {
return InkWell(
child: Container(
height: 40,
child: Column(
children: [
Expanded(
child: Container(
child: Text(dataList[index]
.nameList?[cityIndex]
.name ??
""),
alignment: Alignment.centerLeft,
),
),
Divider(
height: 0.5,
)
],
),
),
onTap: () {},
);
},
itemCount: dataList[index].nameList?.length,
),
)
],
);
},
itemCount: dataList.length,
)
复制代码
ScrollablePositionedListの使用法は、特定のアイテムを見つけることができるもう1つのメソッドがあることを除いて、基本的にListViewの使用法と同じです。
_scrollController.jumpTo(index: i);
复制代码
最終的な効果を見てみましょう。データの繰り返しは無視してください...データを手動で入力するのは面倒です。何もわからない場合は、コミュニケーションをとることができます。
- 概要:このコンポーネントを通じて、Flutterのジェスチャインタラクション操作を簡単に理解できます。ジェスチャ認識を通じて、多くの興味深いコンポーネントを実現できます。特に、描画とアニメーションの組み合わせにより、非常に興味深いインタラクションを作成できます。すべてのインタラクションの最下層は、ジェスチャによるものです。 。識別が完了したら、ソースコードを調べて、共有する時間があります〜