亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Flutter開發(fā)之Widget自定義總結(jié)

 更新時(shí)間:2019年04月05日 12:59:39   作者:kevinxie  
這篇文章主要給大家介紹了關(guān)于Flutter開發(fā)中Widget自定義的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Flutter具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

前言

在Flutter實(shí)際開發(fā)中,大家可能會遇到flutter框架中提供的widget達(dá)不到我們想要的效果,這時(shí)就需要我們?nèi)プ远xwidget,從Flutter構(gòu)建、布局、繪制三部曲中我們了解到,實(shí)際的測量、布局、繪制操作都在RenderObject中,我們是可以進(jìn)行繼承相關(guān)的RenderObject來實(shí)現(xiàn)自定義的。但是其實(shí)flutter框架在設(shè)計(jì)之初就給我們預(yù)留出了自定義的入口,方便我們進(jìn)行自定義。

CustomPaint自定義繪制

例:圓形進(jìn)度條

思路:使用CustomPaint繪制需要的效果

class CircleProgress extends StatelessWidget {
 final Size size;
 final double progress;

 CircleProgress({@required this.size, @required this.progress});

 @override
 Widget build(BuildContext context) {
 return CustomPaint(
 size: size,
 painter: CircleProgressPainter(endDegree: progress * 360),//在Painter中寫真正的繪畫邏輯
 );
 }
}

class CircleProgressPainter extends CustomPainter {
 ...省略

 @override
 void paint(Canvas canvas, Size size) {
 ...繪制的具體邏輯,size是畫布的大小
 }
}

CustomSingleChildLayout對單一child進(jìn)行布局

例:實(shí)現(xiàn)對child約束成正方形

思路:使用CustomSingleChildLayout對child進(jìn)行布局,并約束為正方形

class RectLayout extends StatelessWidget {
 final Widget child;

 RectLayout({@required this.child});

 @override
 Widget build(BuildContext context) {
 return CustomSingleChildLayout(
 delegate: RectLayoutDelegate(),//進(jìn)行布局的代理
 child: child,
 );
 }
}

class RectLayoutDelegate extends SingleChildLayoutDelegate {
 //確定layout的size,constraints是parent傳過來的約束
 @override
 Size getSize(BoxConstraints constraints) => super.getSize(constraints);

 ///是否需要relayout
 @override
 bool shouldRelayout(SingleChildLayoutDelegate oldDelegate) => false;

 ///確定child的位置,返回一個(gè)相對于parent的偏移值,size是layout的大小,由getsize確定,childSize由getConstraintsForChild得出的Constraints對child進(jìn)行約束,得到child自身的size
 @override
 Offset getPositionForChild(Size size, Size childSize) {
 double dx = (size.width - childSize.width) / 2;
 double dy = (size.height - childSize.height) / 2;
 return Offset(dx, dy);
 }

 ///確定child的約束,用于確定child的大小
 @override
 BoxConstraints getConstraintsForChild(BoxConstraints constraints) {//
 double maxEdge = min(constraints.maxWidth, constraints.maxHeight);
 return BoxConstraints(maxWidth: maxEdge, maxHeight: maxEdge);
 }
}

CustomSingleChildLayout對多個(gè)child進(jìn)行布局

例:實(shí)現(xiàn)網(wǎng)格布局

思路:使用CustomSingleChildLayout對child進(jìn)行布局、定位,使其成為網(wǎng)格的布局

class GridLayout extends StatelessWidget {
 final List<Widget> children;
 final double horizontalSpace;
 final double verticalSpace;

 GridLayout(
 {@required this.children,
 @required this.horizontalSpace,
 @required this.verticalSpace});

 @override
 Widget build(BuildContext context) {
 List<Widget> layoutChildren = new List();
 for (int index = 0; index < children.length; index++) {
 layoutChildren.add(LayoutId(id: index, child: children[index]));
 }
 return CustomMultiChildLayout(
 delegate: GridLayoutDelegate(//真正的布局實(shí)現(xiàn)
 horizontalSpace: horizontalSpace,
 verticalSpace: verticalSpace,
 ),
 children: layoutChildren,
 );
 }
}

class GridLayoutDelegate extends MultiChildLayoutDelegate {
 final double horizontalSpace;
 final double verticalSpace;
 List<Size> _itemSizes = List();

 GridLayoutDelegate(
 {@required this.horizontalSpace, @required this.verticalSpace});

 @override
 void performLayout(Size size) {
	//對每個(gè)child進(jìn)行逐一布局
 int index = 0;
 double width = (size.width - horizontalSpace) / 2;
 var itemConstraints = BoxConstraints(
 minWidth: width, maxWidth: width, maxHeight: size.height);
 while (hasChild(index)) {
 _itemSizes.add(layoutChild(index, itemConstraints));
 index++;
 }
	//對每一個(gè)child逐一進(jìn)行定位
 index = 0;
 double dx = 0;
 double dy = 0;
 while (hasChild(index)) {
 positionChild(index, Offset(dx, dy));
 dx = index % 2 == 0 ? width + horizontalSpace : 0;
 if (index % 2 == 1) {
 double maxHeight =
  max(_itemSizes[index].height, _itemSizes[index - 1].height);
 dy += maxHeight + verticalSpace;
 }
 index++;
 }
 }

 @override
 bool shouldRelayout(MultiChildLayoutDelegate oldDelegate) {
 return oldDelegate != this;
 }

 //確定layout的size,constraints是parent傳過來的約束
 @override
 Size getSize(BoxConstraints constraints) => super.getSize(constraints);
}

組合自定義

一般情況,組合自定義應(yīng)該是我們最經(jīng)常用的方式,通過繼承自StatelessWidget或StatefulWidget,把多個(gè)Widget組合起來,從而達(dá)到我們需要的效果。

例:下拉刷新,上拉加載

實(shí)現(xiàn)一:通過自帶的RefreshIndictor和ScrollController組合實(shí)現(xiàn)

思路:通過對滾動進(jìn)行監(jiān)聽來觸發(fā)加載更多

_scrollController.addListener(() {
 var maxScroll = _scrollController.position.maxScrollExtent;
 if (_scrollController.offset >= maxScroll) {
 if (widget.loadMoreStatus != LoadMoreStatus.noData) {
 widget.onLoadMore();
 }
 }
});

實(shí)現(xiàn)二:通過NotificationListener監(jiān)聽scroll的整體狀態(tài),讓后結(jié)合平移、動畫來實(shí)現(xiàn)

思路:通過監(jiān)聽用戶overscroll的距離來平移內(nèi)容區(qū)域,從而達(dá)到下拉刷新,上拉加載的效果

@override
Widget build(BuildContext context) {
 double topHeight =
 _pullDirection == PullDirection.DOWN ? _overScrollOffset.dy.abs() : 0;
 double bottomHeight =
 _pullDirection == PullDirection.UP ? _overScrollOffset.dy.abs() : 0;
 return Stack(
 children: <Widget>[
 widget.headerBuilder.buildTip(_state, topHeight),
 Align(
 alignment: Alignment.bottomCenter,
 child: widget.footerBuilder.buildTip(_state, bottomHeight),
 ),
 Transform.translate(
 offset: _overScrollOffset,
 child: NotificationListener<ScrollNotification>(
  onNotification: handleScrollNotification,
  child: DecoratedBox(
  decoration: BoxDecoration(color: Colors.grey[100]),
  child: ListView.builder(
  itemBuilder: buildItem,
  itemCount: 30,
  ),
  ),
 ),
 )
 ],
 );
}

例:上下左右滑動的layout

實(shí)現(xiàn):通過GestureDetector監(jiān)聽手勢滑動,然后通過平移來達(dá)到效果

思路:主要處理滑動邊界,以及開關(guān)的零界點(diǎn)

@override
Widget build(BuildContext context) {
 //debugPrint('_slideOffset:${_slideOffset.toString()}');
 return GestureDetector(
 onPanUpdate: handlePanUpdate,
 onPanEnd: handlePanEnd,
 child: Stack(
 children: <Widget>[
 widget.background,
 Transform.translate(
  child: widget.foreground,
  offset: _slideOffset,
 ),
 ],
 ),
 );
}

以上的完整代碼在這flutter知識點(diǎn)整理

Flutter學(xué)習(xí)總結(jié)

對Flutter的學(xué)習(xí)也有一段時(shí)間了,從最開始的Widget的使用,到后面的框架的一些研究,所有的心得與總結(jié)都會記錄下來,主要是對自己知識點(diǎn)的整理,同樣也為了能夠與廣大Flutter的學(xué)習(xí)者共同學(xué)習(xí),相互探討。

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對腳本之家的支持。

相關(guān)文章

  • Android 音樂播放器的開發(fā)實(shí)例詳解

    Android 音樂播放器的開發(fā)實(shí)例詳解

    本文主要講解Android 音樂播放器的開發(fā),這里給大家提供一個(gè)簡單的示例代碼,和實(shí)現(xiàn)效果圖,有需要開發(fā)音樂播放器的朋友可以參考下
    2016-08-08
  • 簡單學(xué)習(xí)Android TextView

    簡單學(xué)習(xí)Android TextView

    這篇文章主要和大家一起簡單學(xué)習(xí)Android TextView,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • android中多線程下載實(shí)例

    android中多線程下載實(shí)例

    本文以實(shí)例的方式為大家介紹下android中的多線程下載附源碼,感興趣的朋友可以學(xué)習(xí)下哈
    2013-06-06
  • Android開發(fā)實(shí)現(xiàn)自動切換文字TextSwitcher功能示例

    Android開發(fā)實(shí)現(xiàn)自動切換文字TextSwitcher功能示例

    這篇文章主要介紹了Android開發(fā)實(shí)現(xiàn)自動切換文字TextSwitcher功能,結(jié)合實(shí)例形式詳細(xì)分析了Android使用TextSwitcher實(shí)現(xiàn)文字自動切換的原理、實(shí)現(xiàn)方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下
    2019-03-03
  • 淺談Android中線程池的管理

    淺談Android中線程池的管理

    本篇文章主要介紹了淺談Android中線程池的管理,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-01-01
  • Flutter Set存儲自定義對象時(shí)保證唯一的方法詳解

    Flutter Set存儲自定義對象時(shí)保證唯一的方法詳解

    在Flutter中,Set和List是兩種不同的集合類型,List中存儲的元素可以重復(fù),Set中存儲的元素不可重復(fù),如果想在Set中存儲自定義對象,需要確保對象的唯一性,那么如何保證唯一,接下來小編就給大家詳細(xì)的介紹一下
    2023-11-11
  • Android實(shí)現(xiàn)秒表功能

    Android實(shí)現(xiàn)秒表功能

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)簡易秒表功能,具備啟停功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-09-09
  • Android來電監(jiān)聽和去電監(jiān)聽實(shí)現(xiàn)代碼

    Android來電監(jiān)聽和去電監(jiān)聽實(shí)現(xiàn)代碼

    本文是關(guān)于來點(diǎn)監(jiān)聽和去電監(jiān)聽展開問題,通過實(shí)例代碼講解,對android來電監(jiān)聽和去電監(jiān)聽的相關(guān)知識感興趣的朋友一起看看吧
    2017-06-06
  • Android實(shí)現(xiàn)伸縮彈力分布菜單效果的示例

    Android實(shí)現(xiàn)伸縮彈力分布菜單效果的示例

    本文介紹下在Android中實(shí)現(xiàn)伸縮彈力分布菜單效果。這種效果比較炫酷,有需要的朋友可以參考一下。
    2016-10-10
  • Android自定義水波紋底部導(dǎo)航的實(shí)現(xiàn)

    Android自定義水波紋底部導(dǎo)航的實(shí)現(xiàn)

    TabLayout作為導(dǎo)航組件來說,使用場景非常的多,也意味著要滿足各種各樣的需求,這篇文章主要介紹了Android自定義水波紋底部導(dǎo)航的實(shí)現(xiàn)
    2022-08-08

最新評論