一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Fragment 番外篇——TabLayout+ViewPager+Fragment

 codingSmart 2021-10-22

作者:忘了12138
地址:http://www.cnblogs.com/wangle12138/p/8419496.html
聲明:本文是 忘了12138 原創(chuàng)投稿,轉(zhuǎn)發(fā)等請聯(lián)系原作者授權(quán)。

該文章是一個系列文章,是本人在Android開發(fā)的漫漫長途上的一點(diǎn)感想和記錄,我會盡量按照先易后難的順序進(jìn)行編寫該系列。該系列引用了《Android開發(fā)藝術(shù)探索》以及《深入理解Android 卷Ⅰ,Ⅱ,Ⅲ》中的相關(guān)知識,另外也借鑒了其他的優(yōu)質(zhì)博客,在此向各位大神表示感謝,膜拜!??!

前言

上一篇文章中我們使用底部導(dǎo)航+Fragment的方式實(shí)現(xiàn)了Android主流App中大都存在的設(shè)計。并命名其為“Fragment最佳實(shí)踐”,作為想到單獨(dú)使用Fragment的用戶來說,這個說法并不夸大,它解決了許多用戶在使用Fragment時產(chǎn)生的這樣那樣可見或不可見的問題。不過Fragment還有其他的使用方式,就是我們本章要介紹的。(本來是介紹ListView的,等著ListView的讀者不好意思了,我會很快更新的。)

注:為什么臨時插入這一章,因?yàn)橛凶x者在上一篇文章中評論了,我覺得大有道理,感謝


這里我就不打碼了,,哈哈哈哈

TabLayout

TabLayout的靜態(tài)使用

TabLayout是Android 5.0之后Google提供的一系列Material Design設(shè)計規(guī)范中的一個控件。我們在布局文件中可以這樣使用。

   <android.support.design.widget.TabLayout
       android:id="@+id/tab_layout"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_alignParentBottom="true"
       app:tabIndicatorHeight="0dp"
       app:tabSelectedTextColor="@color/colorPrimary"
       >


       <android.support.design.widget.TabItem
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="Tab 1"/>

       <android.support.design.widget.TabItem
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="Tab 2"/>

       <android.support.design.widget.TabItem
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="Tab 3"/>

   </android.support.design.widget.TabLayout>

TabLayout間接繼承于ViewGroup,其內(nèi)可包含0到n個TabItem,這個TabItem就是我們經(jīng)常使用的標(biāo)簽,其是個自定義View,這樣我們就定義了一個包含3個標(biāo)簽頁的TabLayout。其運(yùn)行結(jié)果如下圖:


TabLayout的動態(tài)使用

在布局文件中我們可以很方便定義頂部/底部 導(dǎo)航的布局。我們來看一下在代碼中的使用

   public class TabActivity extends AppCompatActivity {
       @BindView(R.id.tab_layout)
       TabLayout mTabLayout;
       @BindView(R.id.view_pager)
       ViewPager mViewPager;

       @Override
       protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_tab);
           ButterKnife.bind(this);

           mTabLayout.addTab(mTabLayout.newTab().setText("Tab 1"));
           mTabLayout.addTab(mTabLayout.newTab().setText("Tab 2"));
           mTabLayout.addTab(mTabLayout.newTab().setText("Tab 3"));

           //為TabLayout添加Tab選擇事件監(jiān)聽
           mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
               @Override
               public void onTabSelected(TabLayout.Tab tab) {//當(dāng)標(biāo)簽被選擇時回調(diào)

               }

               @Override
               public void onTabUnselected(TabLayout.Tab tab) {//當(dāng)標(biāo)簽從選擇變?yōu)榉沁x擇時回調(diào)

               }

               @Override
               public void onTabReselected(TabLayout.Tab tab) {//當(dāng)標(biāo)簽被重新選擇時回調(diào)

               }
           });

       }
   }

關(guān)于運(yùn)行結(jié)果我就不上圖了,跟上面的運(yùn)行結(jié)果是一樣的。

TabLayout的更多屬性

關(guān)于TabLayout的更多屬性以及使用的說明請查看其官方文檔。在這里我們只關(guān)心TabLayout+ViewPager的化學(xué)反應(yīng),這個組合也是我們平常在開發(fā)中使用最多的。在此之前我們先介紹ViewPager

ViewPager
先看看官方對ViewPager的說明

/*
Layout manager that allows the user to flip left and right
through pages of data.  You supply an implementation of a
{@link PagerAdapter} to generate the pages that the view shows.
ViewPager is most often used in conjunction with {@link android.app.Fragment}
There are standard adapters implemented for using fragments with the ViewPager,
which cover the most common use cases.  These are
{@link android.support.v4.app.FragmentPagerAdapter} and
{@link android.support.v4.app.FragmentStatePagerAdapter};*/

public class ViewPager extends ViewGroup {
}

上面英文的大致意思是ViewPager是一個布局管理類,這個類呢允許用戶左右翻轉(zhuǎn)頁面。你必須實(shí)現(xiàn)一個PagerAdapter來生成這些顯示的頁面。ViewPager經(jīng)常和Fragment一起使用。而且呢Google非常貼心的提供了兩個類FragmentPagerAdapter和FragmentStatePagerAdapter來應(yīng)付那些一般場景。

其實(shí)從ViewPager的說明中,我們基本上就能知道ViewPager是什么以及如何使用了。

PagerAdapter

ViewPager繼承于ViewGroup,官方指導(dǎo)中就說了,你要自己實(shí)現(xiàn)PagerAdapter來生成顯示的頁面,那么我們來看看這個PagerAdapter

/**
* Base class providing the adapter to populate pages inside of
* a {@link ViewPager}.  You will most likely want to use a more
* specific implementation of this, such as
* {@link android.support.v4.app.FragmentPagerAdapter} or
* {@link android.support.v4.app.FragmentStatePagerAdapter}.
*
* <p>When you implement a PagerAdapter, you must override the following methods
* at minimum:</p>
* <ul>
* <li>{@link #instantiateItem(ViewGroup, int)}</li>
* <li>{@link #destroyItem(ViewGroup, int, Object)}</li>
* <li>{@link #getCount()}</li>
* <li>{@link #isViewFromObject(View, Object)}</li>
* </ul>
* /
public abstract class PagerAdapter {
}

其實(shí)我們在看一個不太了解的類的時候,通過源碼上的關(guān)于這個類的說明就可以知道很多信息了。關(guān)于PagerAdapter的說明就是如此。
先說了一下PagerAdapter的作用,是一個基類提供適配器給ViewPager中的頁面,如果你想使用特定的實(shí)現(xiàn)類,那么你可以看兩個類FragmentPagerAdapter和FragmentStatePagerAdapter,這兩個類繼承了PagerAdapter,并實(shí)現(xiàn)了其抽象方法。

后面一段的意思是你如果想自定義你自己的PagerAdapter,那么你最少要實(shí)現(xiàn)這4個方法

  1. instantiateItem(ViewGroup, int)

  2. destroyItem(ViewGroup, int, Object)

  3. getCount()

  4. isViewFromObject(View, Object)

下面我們以代碼的形式,說明這4個方法的含義以及如何使用

private class MyViewPagerAdapter extends PagerAdapter {
   /**
     * 獲取View的總數(shù)
     *
     * @return View總數(shù)
     */

   @Override
   public int getCount() {
       return 0;
   }
   /**
    * 為給定的位置創(chuàng)建相應(yīng)的View。創(chuàng)建View之后,需要在該方法中自行添加到container中。
    *
    * @param container ViewPager本身
    * @param position  給定的位置
    * @return 提交給ViewPager進(jìn)行保存的實(shí)例對象
    */

   @Override
   public Object instantiateItem(ViewGroup container, int position) {
       return super.instantiateItem(container, position);
   }
   /**
    * 給定的位置移除相應(yīng)的View。
    *
    * @param container ViewPager本身
    * @param position  給定的位置
    * @param object    在instantiateItem中提交給ViewPager進(jìn)行保存的實(shí)例對象
    */

   @Override
   public void destroyItem(ViewGroup container, int position, Object object) {
       super.destroyItem(container, position, object);
   }
   /**
    * 確認(rèn)View與實(shí)例對象是否相互對應(yīng)。ViewPager內(nèi)部用于獲取View對應(yīng)的ItemInfo。
    *
    * @param view   ViewPager顯示的View內(nèi)容
    * @param object 在instantiateItem中提交給ViewPager進(jìn)行保存的實(shí)例對象
    * @return 是否相互對應(yīng)
    */

   @Override
   public boolean isViewFromObject(View view, Object object) {
       return false;
   }
}

這4個方法是必須的,,另外還有一些不是必須,但是可能會用到的

/**
* 當(dāng)ViewPager的內(nèi)容有所變化時,進(jìn)行調(diào)用。
*
* @param container ViewPager本身
*/

@Override
public void startUpdate(ViewGroup container) {
   super.startUpdate(container);
}
/**
* ViewPager調(diào)用該方法來通知PageAdapter當(dāng)前ViewPager顯示的主要項(xiàng),提供給用戶對主要項(xiàng)進(jìn)行操作的方法。
*
* @param container ViewPager本身
* @param position  給定的位置
* @param object    在instantiateItem中提交給ViewPager進(jìn)行保存的實(shí)例對象
*/

@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
   super.setPrimaryItem(container, position, object);
}
/**
* 較多的用于Design庫中的TabLayout與ViewPager進(jìn)行綁定時,提供顯示的標(biāo)題。
*
* @param position 給定的位置
* @return 顯示的標(biāo)題
*/

@Override
public CharSequence getPageTitle(int position) {
   return super.getPageTitle(position);
}

FragmentPagerAdapter

上面呢只是列舉說明了一下PagerAdapter,看起來有些枯燥,都是些說明,那么我們來看一下實(shí)踐,ViewPager通暢跟Fragment一起使用,即其所管理的頁面通暢是Fragment,所以Google提供了兩個適配器FragmentPagerAdapter和FragmentStatePagerAdapter,我們這節(jié)分析FragmentPagerAdapter。

/**
*真是不看不知道,一看嚇一跳。FragmentPagerAdapter也是個抽象類,
*
*/

public abstract class FragmentPagerAdapter extends PagerAdapter {
   private static final String TAG = "FragmentPagerAdapter";
   private static final boolean DEBUG = false;
   private final FragmentManager mFragmentManager;
   private FragmentTransaction mCurTransaction = null;
   private Fragment mCurrentPrimaryItem = null;
   public FragmentPagerAdapter(FragmentManager fm) {
       mFragmentManager = fm;
   }
   /**
    *抽象方法,看來這個函數(shù)要子類自己實(shí)現(xiàn)了
    *
     * @param position ViewPager中Item的位置
    * @return 位置相關(guān)聯(lián)的Fragment
    */

   public abstract Fragment getItem(int position);
   @Override
   public void startUpdate(ViewGroup container) {
       if (container.getId() == View.NO_ID) {
           throw new IllegalStateException("ViewPager with adapter " + this
                   + " requires a view id");
       }
   }
     /**
    * 為給定的位置創(chuàng)建相應(yīng)的fragment。創(chuàng)建fragment之后,需要在該方法中自行添加到container中。
    *
    * @param container ViewPager本身
    * @param position  給定的位置
    * @return 提交給ViewPager進(jìn)行保存的實(shí)例對象,這里是Fragment
    */

   @Override
   public Object instantiateItem(ViewGroup container, int position) {
       if (mCurTransaction == null) {
           mCurTransaction = mFragmentManager.beginTransaction();
       }
       final long itemId = getItemId(position);
       String name = makeFragmentName(container.getId(), itemId);
       Fragment fragment = mFragmentManager.findFragmentByTag(name);
       if (fragment != null) {
           if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
           mCurTransaction.attach(fragment);
       } else {
           fragment = getItem(position);
           if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
           mCurTransaction.add(container.getId(), fragment,
                   makeFragmentName(container.getId(), itemId));
       }
       if (fragment != mCurrentPrimaryItem) {
           fragment.setMenuVisibility(false);
           fragment.setUserVisibleHint(false);
       }
       return fragment;
   }
     /**
    * 移除給定的位置相應(yīng)的fragment。
    *
    * @param container ViewPager本身
    * @param position  給定的位置
    * @param object    在instantiateItem中提交給ViewPager進(jìn)行保存的實(shí)例對象
    */

   @Override
   public void destroyItem(ViewGroup container, int position, Object object) {
       if (mCurTransaction == null) {
           mCurTransaction = mFragmentManager.beginTransaction();
       }
       if (DEBUG) Log.v(TAG, "Detaching item #" + getItemId(position) + ": f=" + object
               + " v=" + ((Fragment)object).getView());
       mCurTransaction.detach((Fragment)object);
   }
   @Override
   public void setPrimaryItem(ViewGroup container, int position, Object object) {
       Fragment fragment = (Fragment)object;
       if (fragment != mCurrentPrimaryItem) {
           if (mCurrentPrimaryItem != null) {
               mCurrentPrimaryItem.setMenuVisibility(false);
               mCurrentPrimaryItem.setUserVisibleHint(false);
           }
           if (fragment != null) {
               fragment.setMenuVisibility(true);
               fragment.setUserVisibleHint(true);
           }
           mCurrentPrimaryItem = fragment;
       }
   }
   @Override
   public void finishUpdate(ViewGroup container) {
       if (mCurTransaction != null) {
           mCurTransaction.commitNowAllowingStateLoss();
           mCurTransaction = null;
       }
   }
   @Override
   public boolean isViewFromObject(View view, Object object) {
       return ((Fragment)object).getView() == view;
   }
   @Override
   public Parcelable saveState() {
       return null;
   }
   @Override
   public void restoreState(Parcelable state, ClassLoader loader) {
   }
   /**
    * @param position ViewPager中Item的位置
    * @return 唯一的ItemID
    */

   public long getItemId(int position) {
       return position;
   }
   private static String makeFragmentName(int viewId, long id) {
       return "android:switcher:" + viewId + ":" + id;
   }
}

代碼比較少,總共也就100多行,邏輯也比較清晰明了,我們來著重分析instantiateItem和destroyItem

   /**
    * 為給定的位置創(chuàng)建相應(yīng)的fragment。創(chuàng)建fragment之后,需要在該方法中自行添加到container中。
    *
    * @param container ViewPager本身
    * @param position  給定的位置
    * @return 提交給ViewPager進(jìn)行保存的實(shí)例對象,這里是Fragment
    */

   @Override
   public Object instantiateItem(ViewGroup container, int position) {
       //開啟事務(wù)
       if (mCurTransaction == null) {
           mCurTransaction = mFragmentManager.beginTransaction();
       }
       //得到指定位置Item的ID
       final long itemId = getItemId(position);
      //根據(jù)id和ViewPager的ID生成item的name
       String name = makeFragmentName(container.getId(), itemId);
       //以name為Tag查找對應(yīng)的Fragment
       Fragment fragment = mFragmentManager.findFragmentByTag(name);
       if (fragment != null) {//如果找到了
           if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
           //調(diào)用事務(wù)的attach
           mCurTransaction.attach(fragment);
       } else {//沒找到
           //通過我們重寫的getItem方法得到相應(yīng)fragment
           fragment = getItem(position);
           if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
           //調(diào)用事務(wù)的add方法,并設(shè)置Tag
           mCurTransaction.add(container.getId(), fragment,
                   makeFragmentName(container.getId(), itemId));
       }
       //如果frament不等于當(dāng)前主要的Item
       if (fragment != mCurrentPrimaryItem) {
           //設(shè)置其Menu不可見
           fragment.setMenuVisibility(false);
           //設(shè)置其不可見
           fragment.setUserVisibleHint(false);
       }
       return fragment;
   }

instantiateItem方法主要功能是為ViewPager生成Item。
那么destroyItem方法的主要功能是銷毀ViwePager內(nèi)的Item

     @Override
   public void destroyItem(ViewGroup container, int position, Object object)
{
       if (mCurTransaction == null) {
           mCurTransaction = mFragmentManager.beginTransaction();
       }
       //調(diào)用事務(wù)的detach方法
       mCurTransaction.detach((Fragment)object);
   }

FragmentStatePagerAdapter

關(guān)于FragmentStatePagerAdapter,讀者可自行分析,代碼也不長。需要注意的地方是,兩者對于destroyItem的不同實(shí)現(xiàn)

@Override
public void destroyItem(ViewGroup container, int position, Object object)
{
   Fragment fragment = (Fragment) object;
   if (mCurTransaction == null) {
       mCurTransaction = mFragmentManager.beginTransaction();
   }
   if (DEBUG) Log.v(TAG, "Removing item #" + position + ": f=" + object
           + " v=" + ((Fragment)object).getView());
   while (mSavedState.size() <= position) {
       mSavedState.add(null);
   }
   mSavedState.set(position, fragment.isAdded()
           ? mFragmentManager.saveFragmentInstanceState(fragment) : null);
   mFragments.set(position, null);
   //調(diào)用事務(wù)的remove方法
   mCurTransaction.remove(fragment);
}

小結(jié)

ViewPager 是個 ViewGroup,與其他布局 LinearLayout 或者其他任意的ViewGroup并無本質(zhì)的不同,它被Google建議與Fragment結(jié)伴使用,也是說ViewPager所包裹的是Fragment布局。ViewPager需要適配器PagerAdapter操作Fragment,這一點(diǎn)就像ListView需要適配器操作其內(nèi)部的Item一樣。

適配器PagerAdapter是個抽象類,并且依照官方說明,我們必須至少實(shí)現(xiàn)其4個重要方法。4個方法可能太多,所以Google提供了FragmentPagerAdapter以及FragmentStatePagerAdapter,這兩個也是抽象類,不過我們的自定義Adapter只需要實(shí)現(xiàn)其中的getItem(int position)方法即可。

關(guān)于FragmentPagerAdapter以及FragmentStatePagerAdapter的不同,我這里再總結(jié)一下。FragmentPagerAdapter銷毀item的時候最終調(diào)用FragmentTransaction的detach()方法,使用detach()會將view從viewtree中刪除,和FragmentStatePagerAdapter中使用的remove()不同,此時fragment的狀態(tài)依然保持著,在使用attach()時會再次調(diào)用onCreateView()來重繪視圖,注意使用detach()后fragment.isAdded()方法將返回false。

實(shí)例

更改后的TabActivity對應(yīng)的布局文件

   <?xml version="1.0" encoding="utf-8"?>
   <RelativeLayout
       xmlns:android="http://schemas./apk/res/android"
       xmlns:app="http://schemas./apk/res-auto"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:fitsSystemWindows="true"

       <!--ViewPager-->

       <android.support.v4.view.ViewPager
           android:id="@+id/view_pager"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:layout_alignParentTop="true"
           >


       </android.support.v4.view.ViewPager>
       <!--分割線-->
       <ImageView
           android:id="@+id/image_1"
           android:layout_width="match_parent"
           android:layout_height="1dp"
           android:background="#919292"
           android:layout_above="@+id/tab_layout"/>


       <!--TabLayout-->
       <android.support.design.widget.TabLayout
           android:id="@+id/tab_layout"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:layout_alignParentBottom="true"
           app:tabIndicatorHeight="0dp"
           app:tabSelectedTextColor="@color/colorPrimary"
           >


       </android.support.design.widget.TabLayout>

   </RelativeLayout>

更改后的TabActivity

   public class TabActivity extends AppCompatActivity {
       @BindView(R.id.tab_layout)
       TabLayout mTabLayout;
       @BindView(R.id.view_pager)
       ViewPager mViewPager;

       @Override
       protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_tab);
           ButterKnife.bind(this);

           mTabLayout.addTab(mTabLayout.newTab().setText("Tab 1"));
           mTabLayout.addTab(mTabLayout.newTab().setText("Tab 2"));
           mTabLayout.addTab(mTabLayout.newTab().setText("Tab 3"));

           //自定義的Adapter繼承自FragmentPagerAdapter
           final PagerAdapter adapter = new PagerAdapter
               (getSupportFragmentManager(), mTabLayout.getTabCount());

           //ViewPager設(shè)置Adapter
           mViewPager.setAdapter(adapter);

           //為ViewPager添加頁面改變監(jiān)聽
           mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mTabLayout));

           //為TabLayout添加Tab選擇監(jiān)聽

           mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
               @Override
               public void onTabSelected(TabLayout.Tab tab) {
                   mViewPager.setCurrentItem(tab.getPosition());
               }

               @Override
               public void onTabUnselected(TabLayout.Tab tab) {

               }

               @Override
               public void onTabReselected(TabLayout.Tab tab) {

               }
           });

       }

   }

而我們自定義的MyPagerAdapter也非常簡單

public class MyPagerAdapter extends FragmentPagerAdapter {
   //fragment的數(shù)量
   int nNumOfTabs;
   public MyPagerAdapter(FragmentManager fm, int nNumOfTabs)
   
{
       super(fm);
       this.nNumOfTabs=nNumOfTabs;
   }
   /**
    * 重寫getItem方法
    *
    * @param position 指定的位置
    * @return 特定的Fragment
    */

   @Override
   public Fragment getItem(int position) {
       switch(position)
       {
           case 0:
               GoodsFragment tab1=new GoodsFragment();
               return tab1;
           case 1:
               CategoryFragment tab2=new CategoryFragment();
               return tab2;
           case 2:
               TaskFragment tab3=new TaskFragment();
               return tab3;
       }
       return null;
   }
   /**
    * 重寫getCount方法
    *
    * @return fragment的數(shù)量
    */

   @Override
   public int getCount() {
       return nNumOfTabs;
   }
}

ViewPager預(yù)加載與懶加載

ViewPager的預(yù)加載機(jī)制

ViewPager可通過setOffscreenPageLimit(int limit)函數(shù)設(shè)置ViewPager預(yù)加載的View數(shù)目

public void setOffscreenPageLimit(int limit) {
   //DEFAULT_OFFSCREEN_PAGES=1
   if (limit < DEFAULT_OFFSCREEN_PAGES) {
       Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to "
               + DEFAULT_OFFSCREEN_PAGES);
       limit = DEFAULT_OFFSCREEN_PAGES;
   }
   if (limit != mOffscreenPageLimit) {
       mOffscreenPageLimit = limit;
       populate();
   }
}

本篇總結(jié)

我們在本篇博客中比較詳細(xì)的探討了TabLayout+ViewPager+Fragment的使用,我們在許多主流App中都能看到這種頂部、底部導(dǎo)航的效果,并且在此基礎(chǔ)上我們探討了TabLayout+ViewPager+Fragment懶加載問題。

下篇預(yù)告

下篇打算往Fragment中加點(diǎn)東西,ListView

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    免费播放一区二区三区四区| 午夜精品国产精品久久久| 东京热一二三区在线免| 国产午夜精品在线免费看| 美女被后入福利在线观看| 久久机热频这里只精品| 日韩欧美三级中文字幕| 九九热精品视频在线观看| 好吊日成人免费视频公开| 亚洲国产av在线视频| 91精品国产av一区二区| 日韩欧美综合在线播放| 91人妻人澡人人爽人人精品| 亚洲伊人久久精品国产| 在线观看免费无遮挡大尺度视频| 国产成人人人97超碰熟女| 久久热在线免费视频精品| 亚洲精选91福利在线观看| 久久精品国产99精品最新| 日韩人妻av中文字幕| 久久精品久久精品中文字幕| 五月情婷婷综合激情综合狠狠| 尤物久久91欧美人禽亚洲| 成人精品一区二区三区综合| 亚洲最新一区二区三区| 欧美日韩人妻中文一区二区| 91精品国产综合久久不卡| 久久精品国产熟女精品| 偷拍偷窥女厕一区二区视频| 午夜精品国产精品久久久| 欧美一区二区三区五月婷婷| 亚洲国产精品无遮挡羞羞| 日本在线 一区 二区| 国产黑人一区二区三区| 国产欧美一区二区色综合| 蜜桃传媒在线正在播放| 欧美91精品国产自产| 免费亚洲黄色在线观看| 亚洲男人天堂网在线视频| 亚洲最新中文字幕在线视频 | 午夜福利精品视频视频|