精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

一文讓你理清PrimaryScrollController

移動開發
對蘋果用戶來說,大家基本都知道,iOS手機應用有一個比較常見的功能:點擊狀態欄,列表就會滾動到頂部。在iOS原生代碼中,我們可以通過原生框架的已有特性或者自己添加監聽來實現這個功能。

PrimaryScrollController的作用

對蘋果用戶來說,大家基本都知道,iOS手機應用有一個比較常見的功能:點擊狀態欄,列表就會滾動到頂部。

在iOS原生代碼中,我們可以通過原生框架的已有特性或者自己添加監聽來實現這個功能。

那么在flutter中有沒有呢?答案當然是肯定的。

flutter專門為iOS端做了這一個支持,可以讓我們快速的實現點擊狀態欄回頂部的效果,它就是一系列圍繞PrimaryScrollController數據傳遞方式所展開的設計。

按照我們早期flutter開發經驗,如果沒有仔細的對PrimaryScrollController和相關類的實現有詳細的了解,必然會在構建結構復雜的頁面時出現各種奇怪的問題。

PrimaryScrollController的定義

PrimaryScrollController的源碼內容并不多,主要包含兩部分。

  • 擴展自InheritedWidget
  • 持有ScrollController類型的變量

下面是源碼部分:

class PrimaryScrollController extends InheritedWidget {

const PrimaryScrollController({
Key? key,
required ScrollController this.controller,
required Widget child,
}) : assert(controller != null),
super(key: key, child: child);


const PrimaryScrollController.none({
Key? key,
required Widget child,
}) : controller = null,
super(key: key, child: child);

final ScrollController? controller;


static ScrollController? of(BuildContext context) {
final PrimaryScrollController? result = context.dependOnInheritedWidgetOfExactType<PrimaryScrollController>();
return result?.controller;
}
...
}

關于InheritedWidget

InheritedWidget可以說是flutter框架內比較常見的數據傳遞設計抽象,簡單介紹一下。

?

每個Element實例都持有一個_inheritedWidgets?,每當要為Widget添加特定類型的依賴時,就會從該集合里取出相關類型的InheritedElement實例。

而element的_inheritedWidgets是在每次element掛載和重新啟用時,element都會從它的上層element中打包拿到其所持有的所有_inheritedWidgets。

還有特殊的InheritedElement? 它繼承了Element?,相較于普通的Element,InheritedElement?不僅會拿到其上層element所有的_inheritedWidgets,而且會將自己也作為一個元素添加到集合中

自定義 InheritedWidgetA:

class InheritedWidgetA extends InheritedWidget {
Value a;
...
static Value? of(BuildContext context) {
final InheritedWidgetA? result =
context.dependOnInheritedWidgetOfExactType<InheritedWidgetA>();
return result?.a;
}
}

使用示例和數據傳遞如下:

圖片

inheritedWidget數據圖

如上圖所示:childA,childB都能共享上級樹的數據。

ScrollController

ScrollController?間接繼承自Listenable,主要有兩個功能

  • 監聽滾動事件
  • 控制列表滾動

ScrollController部分實現:

class ScrollController extends ChangeNotifier {
...
void jumpTo(double value) {
assert(_positions.isNotEmpty, 'ScrollController not attached to any scroll views.');
for (final ScrollPosition position in List<ScrollPosition>.of(_positions))
position.jumpTo(value);
}




void attach(ScrollPosition position) {
assert(!_positions.contains(position));
_positions.add(position);
position.addListener(notifyListeners);
}




void detach(ScrollPosition position) {
assert(_positions.contains(position));
position.removeListener(notifyListeners);
_positions.remove(position);
}

}

看源碼發現:

ScrollController?提供了綁定和解綁ScrollPosition?。 每個ScrollPosition?對應一個Scrollable?滾動視圖 ,注意ScrollController?是可以綁定多個ScrollPosition。

所以通過scrollController.position直接取值報錯可能是大多數朋友會踩的坑。

ScrollPosition get position {
assert(_positions.isNotEmpty, 'ScrollController not attached to any scroll views.');
assert(_positions.length == 1, 'ScrollController attached to multiple scroll views.');
return _positions.single;
}

ScrollView與ScrollController的聯系:

ScrollView?創建時是需要兩個參數controller和primary?的,主要用來確定綁定的scrollController是使用controller?還是最近的父級PrimaryScrollController中的scrollController。

abstract class ScrollView extends StatelessWidget {
final ScrollController? controller;
final bool primary;

@override
Widget build(BuildContext context) {
final List<Widget> slivers = buildSlivers(context);
final AxisDirection axisDirection = getDirection(context);


final ScrollController? scrollController =
primary ? PrimaryScrollController.of(context) : controller;

final Scrollable scrollable = Scrollable(
controller: scrollController,
);
...
return scrollable;
}

}

可以看到在ScrollView?中會創建Scrollable,Scrollable?會在_updatePosition?時與ScrollController?進行綁定,接著ScrollController就能控制視圖滾動,或者監聽視圖滾動。

class ScrollableState extends State<Scrollable> with TickerProviderStateMixin, RestorationMixin
implements ScrollContext {




ScrollPosition get position => _position!;
ScrollPosition? _position;

final _RestorableScrollOffset _persistedScrollOffset = _RestorableScrollOffset();

@override
AxisDirection get axisDirection => widget.axisDirection;

late ScrollBehavior _configuration;
ScrollPhysics? _physics;
ScrollController? _fallbackScrollController;
MediaQueryData? _mediaQueryData;

ScrollController get _effectiveScrollController => widget.controller ?? _fallbackScrollController!;


void _updatePosition() {
_configuration = widget.scrollBehavior ?? ScrollConfiguration.of(context);
_physics = _configuration.getScrollPhysics(context);
if (widget.physics != null) {
_physics = widget.physics!.applyTo(_physics);
} else if (widget.scrollBehavior != null) {
_physics = widget.scrollBehavior!.getScrollPhysics(context).applyTo(_physics);
}
final ScrollPosition? oldPosition = _position;
if (oldPosition != null) {
_effectiveScrollController.detach(oldPosition);



scheduleMicrotask(oldPosition.dispose);
}

_position = _effectiveScrollController.createScrollPosition(_physics!, this, oldPosition);
assert(_position != null);
_effectiveScrollController.attach(position);
}

}

到這里已經介紹完了PrimaryScrollController?的實現以及相關的類與其的關系,接下來,我們看一下Flutter官方是怎么利用PrimaryScrollController?來設計點擊狀態欄回頂部功能的,看看Flutter還在哪些內部組件埋下了關于PrimaryScrollController的處理。

Scaffold

到目前為止,我們只談了PrimaryScrollController的使用,那么思考一下:點擊狀態欄事件的監聽是在哪里實現的?是如何對應到每個具體頁面的?

你猜對了,在Scaffold中。Scaffold是基于Material上的一種視覺支架,可以很方便的作出類似iOS風格的交互和UI。Flutter官方在Scaffold中添加了狀態欄區域的gesture并處理了點擊事件。看源碼:

class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, RestorationMixin {

@override
Widget build(BuildContext context) {
...
switch (themeData.platform) {
case TargetPlatform.iOS:
case TargetPlatform.macOS:
_addIfNonNull(
children,
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: _handleStatusBarTap,

excludeFromSemantics: true,
),
_ScaffoldSlot.statusBar,
removeLeftPadding: false,
removeTopPadding: true,
removeRightPadding: false,
removeBottomPadding: true,
);
break;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
case TargetPlatform.windows:
break;
}
...
}




void _handleStatusBarTap() {
final ScrollController? _primaryScrollController = PrimaryScrollController.of(context);
if (_primaryScrollController != null && _primaryScrollController.hasClients) {
_primaryScrollController.animateTo(
0.0,
duration: const Duration(milliseconds: 300),
curve: Curves.linear,
);
}
}

}

可以看到,Scaffold中添加了狀態欄位置的點擊,并在點擊后通過 PrimaryScrollController.of(context) 獲取scrollController,最后調整滾動位置。

此時我們已經知道了狀態欄監聽使用PrimaryScrollController.of(context)?進行了控制滾動,ScrollView 綁定了PrimaryScrollController.of(context) 。

好了,到目前為止,我們可以看下面的例子:一般情況下我們的項目代碼是下面這樣

runApp(
MaterialApp(
theme: ThemeData(
platform: TargetPlatform.iOS,
primarySwatch: Colors.blue,
),
routes: kkConfigureRoutes(),
initialRoute: "/",
)
);


class PageAState {
Widget build(BuildContext context) {
super.build(context);
return Scaffold(
child:ListView(
primary:true
controller:null
...
)
);
}
}

當你push到PageA時,接著點擊狀態欄,PageA中的列表回到了頂部。感覺好像沒什么問題,但是好像缺了點什么,對嗎?

對!?? 你發現了,我們并沒有創建PrimaryScrollController? 和 Scrollcontroller。那么Scaffold中取的PrimaryScrollController來自哪里?

PrimaryScrollController  的默認創建

在上面PageAState中你會發現:PrimaryScrollController.of(context) 是有值的。所以答案只能是在push到頁面pageA時,就創建了PrimaryScrollController和Scrollcontroller。猜測flutter應該是在router層給大家自動創建了。我們尋找一下源碼,發現在routes.dart的_ModalScope中,套了一層 PrimaryScrollController(controller:primaryScrollController)。

class _ModalScopeState<T> extends State<_ModalScope<T>> {




....
final ScrollController primaryScrollController = ScrollController();

@override
Widget build(BuildContext context) {
return ...
child: PrimaryScrollController(
controller: primaryScrollController,
...
)
}
}

路由每產生一級ModalScopeState,會創建ScrollController(), 并添加PrimaryScrollController Widget。頁面Page作為子Wideget就可以獲取到上級的ScrollController。

使用流程小結

上面講了這么多,現在我們可以總結一下,正確優雅的使用官方提供的點擊狀態欄功能的步驟:

  • 需要通過路由進了頁面
  • 頁面需要使用Scaffold, 這里注意(同一個頁面Scaffold不能嵌套,否則可能無法響應狀態欄點擊事件)
  • Scaffold中有ScrollView
  • PrimaryScrollController.of(context) 綁定了ScrollView

這樣就實現了點擊狀態欄滾動視圖回到頂部功能。

實際問題

我們來看一個比較常見的App結構:打開app,app底部有三個tab,每個tab都有對應的A,B兩個列表頁。下面是代碼:

void main {
runApp(
MaterialApp(
routes: kkConfigureRoutes(),
initialRoute: "/",
)
);
}



class RootTabPageState extends BaseThemeState<RootTabPage> {

late PageController _pageController;
late List<Widget> _tabs;

@override
void initState() {
super.initState();
_tabs = [
PageA(key: _),
PageB(key: _),
];
}

@override
Widget build(BuildContext context) {

return Scaffold(
child:Column(
children:[
Expanded(child: PageView(
children: _tabs,
controller: _pageController,
physics: const NeverScrollableScrollPhysics()
)),
KKBottomBar(...),
]
),
);
}

}



class PageAState with AutomaticKeepAliveClientMixin {
Widget build(BuildContext context) {
super.build(context);
return ListView(
primary:true
controller:null
...
);
}
...
}

class PageBState with AutomaticKeepAliveClientMixin {
Widget build(BuildContext context) {
super.build(context);
return ListView(
primary:true
controller:null
...
);
}
...
}

上面的代碼有點特殊問題,不知道你們發現沒有:如果我點擊狀態欄,頁面的列表會滾動到頂部嗎?分析一下,有Router層創建了PrimaryScrollController,RootTabPageState層包裝了Scaffold監聽點擊狀態欄事件,然后A,B頁面primary=true , 兩個頁面的ScrollView都綁定了父PrimaryScrollController.of(context)。所以點擊狀態欄,列表會回到頂部。但是你會發現PrimaryScrollController.of(context) 綁定了兩個ScrollView。所以點擊狀態欄,兩個列表都會回到頂部,當然如果需求是這樣,那么沒問題,但是我想大部分情況下這是一個問題。所以,我們來試著改一下:

class RootTabPageState extends BaseThemeState<RootTabPage> {

late PageController _pageController;
late List<Widget> _tabs;

@override
void initState() {
super.initState();
_tabs = [
PageA(key: _),
PageB(key: _),
PageC(key: _),
];
}

@override
Widget build(BuildContext context) {

return Material(
child:Column(
children:[
Expanded(child: PageView(
children: _tabs,
controller: _pageController,
physics: const NeverScrollableScrollPhysics()
)),
KKBottomBar(...),
]
),
);
}

}

class PageAState {
Widget build(BuildContext context) {
return Scaffold(
ListView(
primary:true
controller:null
...
)
);
}
...
}

class PageBState {
Widget build(BuildContext context) {

return Scaffold(
ListView(
primary:true
controller:null
...
)
);
}
...
}

我們將RootTabPageState中的Scaffold改成了Material,A,B頁面加上了Scaffold。想想結果是什么?雖然我們添加了兩個Scaffold監聽各自的頁面A,B。但是PrimaryScrollController.of(context) ,其實是Router層創建的,所以PrimaryScrollController.of(context) 還是綁定了兩個頁面的ScrollView。所以點擊狀態欄,兩個列表都會回到頂部。我們繼續調整:

class RootTabPageState extends BaseThemeState<RootTabPage> {

late PageController _pageController;
late List<Widget> _tabs;

@override
void initState() {
super.initState();
_tabs = [
PageA(key: _),
PageB(key: _),
PageC(key: _),
];
}

@override
Widget build(BuildContext context) {

return Material(
child:Column(
children:[
Expanded(child: PageView(
children: _tabs,
controller: _pageController,
physics: const NeverScrollableScrollPhysics()
)),
KKBottomBar(...),
]
),
);
}

}

class PageAState {

final ScrollController _scrollController = ScrollController();

Widget build(BuildContext context) {
return
PrimaryScrollController(
controller: _scrollController,
child: Scaffold(
ListView(
primary:true
controller:null
...
)
)
);
}

...
}

class PageBState {
final ScrollController _scrollController = ScrollController();

Widget build(BuildContext context) {
return
PrimaryScrollController(
controller: _scrollController,
child: Scaffold(
ListView(
primary:true
controller:null
...
)
)
);
}
...
}

我們在A,B頁面自己添加了PrimaryScrollController并創建了_scrollController,這樣PageA中的Scaffold取PrimaryScrollController.of(context) 其實取的是我們創建的_scrollController。PageA中的Scrollview綁定的也是PageA中的_scrollController。所以現在,我們在A頁面點擊狀態欄,那么只有A頁面的列表會回到頂部了。當大家真正了解了上面提到的相關內容后,在你遇到不同的頁面結構時,就知道如何去設計,才能避免一些奇怪的問題。

大家可以思考一下?在上述例子結構中,如果其中PageAState頁面不止包含一個列表,而是本身是一個可以左右滾動的多列表時,該如何實現在頁面A點擊狀態欄,讓頁面A當前顯示的列表回到頂部。

篇幅有限,這里給提供一個思路,每個列表單獨創建ScrollController。PageA層自定義ScrollController類,重寫其滾動方法來接受狀態欄點擊事件,下發到對應列表的ScrollController。

隱秘的問題

接下來,說一個比較隱秘的問題,下面是一個例子:

class PageAState {
final ScrollController _scrollController = ScrollController();

Widget build(BuildContext context) {
super.build(context);
return
PrimaryScrollController(
controller: _scrollController,
Scaffold(
child:ListView(
primary:true
controller:null,
children:[
CellA()
])

);
}
}


class CellAState {

ScrollController? _controller;
@override
Widget build(BuildContext context) {
_controller = PrimaryScrollController.of(context);
return MyButton(
onPress:_press
);
}

void _press(){
_controller?.jumpTo(0);
}
}

上面這個例子中,我想在CellAState中獲取_controller,然后用它來做點事情,比如里面有個按鈕,然后點擊后,讓列表滾動到某個位置。雖然這個例子看起來非常簡單,但是很不幸,你取到的_controller為null,為什么?此時你會檢查代碼,檢查PrimaryScrollController的使用方式是否有問題,在檢查了一輪之后,發現并沒有問題,然后你可能開始有點抓狂。這個例子層級少,比較簡單的,我們可以也許可以通過斷點發現一些端倪,但是在項目中可能層級非常之多,如果通過斷點去找,那將是地獄。沒有辦法,你只能進入地獄,很幸運我們的例子很簡單,這個地獄不是特別深,通過斷點一步一步的,你會發現有一個 PrimaryScrollController.none,回顧一下,這個東西好像在PrimaryScrollController的源碼中出現過。

這個東西是在哪創建的呢???

因為我們例子比較簡單,所以我們能肯定問題發生在List中,但是在項目中這將是一個非常隱秘的問題。我們進入listView, 一層層的進入,最后看到了它的抽象類ScrollView,我們之前提到過。我們再來看下ScrollView的源碼:

abstract class ScrollView extends StatelessWidget {
final ScrollController? controller;
final bool primary;
const ScrollView({
Key? key,
this.controller,
bool? primary,
...
}) : assert(scrollDirection != null),
assert(!(controller != null && (primary ?? false)),
'Primary ScrollViews obtain their ScrollController via inheritance from a PrimaryScrollController widget. '
'You cannot both set primary to true and pass an explicit controller.',
),
primary = primary ?? controller == null && identical(scrollDirection, Axis.vertical),
super(key: key);

@override
Widget build(BuildContext context) {
...
final ScrollController? scrollController =
primary ? PrimaryScrollController.of(context) : controller;
final Scrollable scrollable = Scrollable(
...
);
final Widget scrollableResult = primary && scrollController != null
? PrimaryScrollController.none(child: scrollable)
: scrollable;
...
return scrollableResult;
}

}

我們發現了什么?

final Widget scrollableResult = primary && scrollController != null
? PrimaryScrollController.none(child: scrollable)
: scrollable;

在 primary && scrollController != null的情況下它為我們包裝了一層PrimaryScrollController.none(child: scrollable)  等效于 PrimaryScrollController(controller:null,child:scrollable)。也就是按照我們外部傳prmary = true的情況下,它把我們截斷了。所以回到我們的問題,如果我們要在CellA中想通過PrimaryScrollController.of(context)取值,該如何修改?

class PageAState {
final ScrollController _scrollController = ScrollController();


Widget build(BuildContext context) {
super.build(context);
return
PrimaryScrollController(
controller: _scrollController,
Scaffold(
child:ListView(
primary:false
controller:_scrollController,
children:[
CellA()
])

);
}
}


class CellAState {

ScrollController? _controller;
@override
Widget build(BuildContext context) {
_controller = PrimaryScrollController.of(context);
return MyButton(
onPress:_press
);
}

void _press(){
_controller?.jumpTo(0);
}
}

結語

好了,本篇基本已經到了尾聲了,相信大家以后碰到與PrimaryScrollController相關的問題便不再是問題了。

看完了這一系列內容,我們可以發現PrimaryScrollController?只是flutter設計的一種數據傳遞的方案,只是解決點擊狀態欄使列表滾動到頂部這個問題中的一環。整個問題其實是涉及到了ScroView,ScrollController,Scaffold?以及Router中的_ModalScopeState等,它們或多或少的提供了特殊處理和輔助方式。

不得不說flutter的組件提供了非常強大的功能,但這也可能導致看似無關的組件和類之間,內部其實是有一定聯系的,而且比較隱蔽,所以在部分復雜場景下,可能會出現一些問題,這時候就比較考驗開發者耐心和對各種組件源碼的熟悉度了。

責任編輯:未麗燕 來源: 搜狐技術產品
相關推薦

2025-05-21 09:32:28

2025-06-04 03:21:00

RAGRetrievalGeneratio

2023-03-10 22:08:20

2018-05-21 10:20:22

人工智能機器學習神經網絡

2018-02-02 11:17:42

IaaSPaaSSaaS

2018-05-31 20:49:50

Spark堆內內存優化機制

2024-09-26 07:27:27

2018-06-13 08:33:32

車聯網智能交通互聯網

2021-10-20 08:49:30

Vuexvue.js狀態管理模式

2020-11-12 09:14:25

JAVA.IO、字符編

2019-07-03 15:32:26

路由器網絡系統

2019-11-06 17:00:51

深度學習神經網絡人工智能

2018-02-03 09:59:20

python程序編輯器

2022-03-18 09:45:43

Git分支Linux

2021-01-21 14:26:56

大數據互聯網大數據應用

2018-10-08 15:00:27

物聯網LoRaIOT

2021-09-10 16:10:21

panda透視表語言

2025-05-22 06:23:48

2025-06-17 00:00:00

2024-08-12 12:30:27

點贊
收藏

51CTO技術棧公眾號

欧美男生操女生| 2017欧美狠狠色| 色综合91久久精品中文字幕| 岛国精品一区二区三区| 精品丝袜在线| 欧美国产国产综合| 91成人伦理在线电影| 5月婷婷6月丁香| 免费毛片在线| 国产一区福利在线| 国产91精品黑色丝袜高跟鞋| av片在线免费看| 中文字幕一区日韩精品| 91国偷自产一区二区三区观看| 二级片在线观看| 污视频在线免费| 韩国av一区二区三区四区| 91av在线不卡| 男人的天堂久久久| 经典一区二区| 亚洲精品在线观看网站| 国产裸体免费无遮挡| 国产白丝在线观看| 国产福利精品导航| 日本高清视频精品| aaaaa一级片| 精品视频在线观看免费观看| 日韩欧美国产激情| 香蕉视频免费版| 国产精品久久婷婷| 免费亚洲婷婷| 欧美激情高清视频| 久艹在线观看视频| 精品视频在线播放一区二区三区| 色婷婷激情久久| 免费人成在线观看视频播放| 91精彩视频在线观看| 97久久超碰国产精品| 亚洲一区久久久| 欧美日韩 一区二区三区| 亚洲国产美女| 九九精品在线视频| 神马午夜精品91| 成人激情视频| 亚洲无限av看| 最新中文字幕视频| 亚洲高清极品| 日韩av中文字幕在线免费观看| 三上悠亚 电影| 高清在线一区二区| 777奇米四色成人影色区| 一本岛在线视频| 欧美一级二级视频| 日本韩国精品在线| 北条麻妃在线视频| 欧美日韩五码| 在线精品视频一区二区| 欧美成人黑人猛交| 欧美日韩美女| 在线视频中文字幕一区二区| 成人免费视频久久| 色猫猫成人app| 欧美伊人久久久久久久久影院 | 国产99久久精品一区二区| 日韩免费黄色片| 亚洲激情国产| 欧洲成人免费视频| 久久久久久久久久成人| 久久久成人网| 国产美女91呻吟求| hs视频在线观看| 成人深夜福利app| 久久99精品久久久久久秒播放器 | 中文字幕日本一区二区| 在线观看一区二区精品视频| 最新中文字幕2018| 亚洲男女网站| 日韩欧美不卡在线观看视频| aaa黄色大片| 婷婷精品在线观看| 伊人青青综合网站| 18啪啪污污免费网站| 性xxxx欧美老肥妇牲乱| 欧美黑人极品猛少妇色xxxxx| 国产免费无码一区二区视频| 亚洲视频高清| 日本91av在线播放| 成人黄色免费网| 国产二区国产一区在线观看| 国偷自产av一区二区三区小尤奈| 欧美精品少妇| 成人免费视频在线观看| 日本福利视频一区| 中文在线8资源库| 欧美日韩免费在线视频| 波多野结衣三级视频| 日韩精品免费一区二区夜夜嗨| 亚洲欧美制服丝袜| 紧身裙女教师波多野结衣| 亚洲经典自拍| 国产精品免费一区豆花| 国产一级片视频| 国产欧美精品| 国产综合久久久久久| 国产91免费在线观看| 欧美极品美女视频| 很污的网站在线观看| 欧美成人app| 精品国产污污免费网站入口| 久久成人激情视频| 欧美日韩三级电影在线| 国产精品久久久| 狠狠人妻久久久久久综合| 麻豆一区二区三区| 精品网站在线看| 黄色在线播放网站| 国产精品久久久久久久岛一牛影视 | 国产精品色一区二区三区| 男人c女人视频| 国产综合色激情| 日韩国产高清视频在线| 裸体武打性艳史| 麻豆国产欧美日韩综合精品二区 | 天堂a中文在线| 亚洲天堂成人网| 欧美精品第三页| 久久久久观看| 亚洲大胆人体视频| 日本人妻一区二区三区| 日韩dvd碟片| 欧美精品电影在线| 国产日韩欧美视频在线观看| 久久久精品蜜桃| 成人一区二区免费视频| 国产精品毛片aⅴ一区二区三区| 亚洲精品网站在线播放gif| 一级黄色录像视频| 国产主播一区二区| 亚洲精品成人自拍| 超级碰碰久久| 日本道色综合久久| 国产二级一片内射视频播放| 一区二区影院| 亚洲aⅴ男人的天堂在线观看| 国产一区二区影视| 国产精品久久久久毛片软件| av动漫免费看| 日韩激情啪啪| 青青久久av北条麻妃海外网| 天天干免费视频| 亚洲成人资源网| 9.1在线观看免费| 国产精品xvideos88| 亚洲自拍在线观看| 在线视频中文字幕第一页| 亚洲国产综合91精品麻豆| 国内自拍第二页| 91九色精品国产一区二区| 成人黄色免费在线观看| 欧美一区二区三区| 日韩丝袜情趣美女图片| 欧美日韩人妻精品一区二区三区| 国产一区二区三区四区五区美女 | 亚洲综合专区| 亚洲自拍偷拍视频| 久草免费在线色站| 亚洲国产精久久久久久| 成人免费看片98欧美| 日本欧美在线看| 日韩欧美精品在线不卡| jizz性欧美| 欧美xxxx老人做受| 国产无码精品在线播放| k8久久久一区二区三区| 国产淫片免费看| 伊人久久精品| 欧美裸体男粗大视频在线观看| 性做久久久久久久| 精品magnet| 亚洲精品国产精品国自产网站| 免费人成网站在线观看欧美高清| 亚洲资源在线网| 欧美专区视频| 777国产偷窥盗摄精品视频| 你懂的免费在线观看| 欧美日韩一区二区三区视频| 国产精品一级黄片| 日韩国产成人精品| 三级网在线观看| 琪琪久久久久日韩精品 | 欧美午夜三级| 久久亚洲欧美日韩精品专区| 少妇av在线播放| 欧美性色黄大片| 久草视频中文在线| 久久国产精品99精品国产| 六月婷婷激情网| 日韩在线黄色| 91精品久久久久久久久久久| 女人天堂av在线播放| 亚洲欧美国产日韩中文字幕| 亚洲影院一区二区三区| 五月综合激情日本mⅴ| 国产视频不卡在线| 成人aaaa免费全部观看| av动漫在线播放| 私拍精品福利视频在线一区| 国产中文字幕91| 黄色在线网站噜噜噜| 日韩专区中文字幕| 中文字幕在线观看高清| 国产亚洲午夜高清国产拍精品 | 成人精品一区二区三区四区| 亚洲色欲综合一区二区三区| 91精品国产91久久久久久密臀| 精品午夜一区二区| 精品国产不卡一区二区| 国产精品草莓在线免费观看| 欧美1234区| 久久精品99久久久久久久久 | 91论坛在线播放| 国产精品中文久久久久久| 久久一区二区三区喷水| 国产欧美日韩中文字幕在线| av资源网在线播放| 欧美成人中文字幕| 91成人高清| 国产视频精品xxxx| 精品国产亚洲一区二区麻豆| 欧美性感一区二区三区| 三级视频在线观看| 亚洲第一综合色| 欧美日韩人妻精品一区二区三区 | 美女毛片在线观看| 国产精品不卡视频| 神马久久久久久久久久久| 91亚洲国产成人精品一区二三| 欧美成人乱码一二三四区免费| 噜噜噜在线观看免费视频日韩| 国产成人永久免费视频| 欧美在线二区| 在线观看成人免费| 欧美gayvideo| 一区二区三区四区在线视频| 香蕉久久夜色精品国产更新时间 | 亚洲精品第五页| 91精品国产色综合久久久蜜香臀| 国产精品成人69xxx免费视频| 国产欧美精品一区| 免费看黄色三级| 国产视频一区在线观看| 亚洲av无码一区二区三区人 | 日韩视频在线永久播放| 国产精品福利电影| 欧美精品精品一区| 国产精品毛片一区视频播| 88在线观看91蜜桃国自产| 91丨porny丨在线中文| 欧美视频三区在线播放| 做爰视频毛片视频| 欧美日韩视频专区在线播放| 中文无码av一区二区三区| 欧美丝袜第三区| 怡春院在线视频| 欧美日韩一区小说| 国产乱码精品一区二区三区精东| 9191成人精品久久| www.麻豆av| 日韩高清中文字幕| 国产在线91| 北条麻妃一区二区三区中文字幕| 免费在线看黄网站| 久久成人亚洲精品| 久久青青色综合| 欧美一区二区三区四区在线| 外国成人直播| 国产日韩欧美日韩大片| 成人自拍视频| 精品国产第一页| 国产在线观看91一区二区三区| 一区二区三区的久久的视频| 亚洲激情中文在线| 国产69精品久久久久999小说| 亚洲永久字幕| 日本黄大片一区二区三区| 国内久久婷婷综合| 亚洲の无码国产の无码步美| 国产亚洲制服色| 欧美日韩精品亚洲精品| 日韩欧美国产骚| 999久久久久久| 亚洲精品中文字幕女同| 看黄网站在线| 97人人做人人爱| 国产精品亲子伦av一区二区三区| 3d精品h动漫啪啪一区二区| 日韩理论电影中文字幕| 一区二区三区欧美成人| 亚洲国产片色| 亚洲成人天堂网| www..com久久爱| 99在线视频免费| 亚洲成av人片在线观看无码| 中文字幕乱码一区二区 | 国产精品看片资源| 97色成人综合网站| 成人黄色在线观看| 精品亚洲自拍| 一区二区三区不卡在线| 亚洲一区日韩在线| 久久久福利影院| 久久久久久一级片| 久久精品视频国产| 欧美日韩国产bt| 神马久久精品| 欧美激情图片区| 国产亚洲精彩久久| 欧美精品久久久| 国内自拍一区| 日韩av片专区| 久久久三级国产网站| 日韩精品一区二区三| 5858s免费视频成人| 国产51人人成人人人人爽色哟哟| 久久久久久九九九| vam成人资源在线观看| 欧洲精品一区色| 国产日韩欧美| 在线xxxxx| 久久在线观看免费| 久久国产在线视频| 制服丝袜av成人在线看| 福利片在线看| 奇米一区二区三区四区久久| 高潮久久久久久久久久久久久久| 一级一片免费播放| 青草国产精品久久久久久| 91国模少妇一区二区三区| 亚洲成av人片| 黄色av网址在线| 久久久久久久97| 激情视频极品美女日韩| 国产精品视频一二三四区| 国内精品久久久久影院薰衣草 | 人人狠狠综合久久亚洲婷| 春日野结衣av| 91啪亚洲精品| 日韩精品在线观看免费| 日韩精品免费在线| 欧产日产国产精品视频| 精品蜜桃传媒| 亚洲一区观看| 欧美老熟妇乱大交xxxxx| 色综合天天综合在线视频| 日本中文字幕电影在线观看 | 99久re热视频精品98| 久久爱www久久做| 在线看的片片片免费| 日韩一级精品视频在线观看| 2021国产在线| 成人欧美一区二区三区视频xxx| 欧美日韩在线大尺度| 成人做爰69片免费| 午夜成人在线视频| 亚洲av成人无码久久精品老人 | 国产精品一区二区男女羞羞无遮挡| 成人18视频免费69| 欧美精品丝袜久久久中文字幕| 国产cdts系列另类在线观看| 亚洲va久久久噜噜噜| 自拍偷拍欧美专区| 午夜剧场免费看| 色综合久久综合网97色综合| 看电影就来5566av视频在线播放| 国产精品黄色av| 91精品国产自产拍在线观看蜜| 亚洲欧美日本一区二区| 亚洲高清免费在线| 免费成人av电影| 国产免费一区视频观看免费 | 欧美区在线播放| 激情小说一区| 亚洲污视频在线观看| 亚洲图片激情小说| 五月婷婷久久久| 国产精品免费久久久| 亚洲天堂免费| 久久人人爽人人人人片| 欧美艳星brazzers| 日本在线视频www鲁啊鲁| 欧美性天天影院| 国产又粗又猛又爽又黄91精品| 国产污视频在线看| 国产一区二区三区欧美| 在线不卡一区| www.99热这里只有精品| 国产精品久久久久影视| 高清国产mv在线观看| 国产精品欧美风情| 国模一区二区三区|