日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android自定义View之仿QQ侧滑菜单实现

發布時間:2025/4/5 Android 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android自定义View之仿QQ侧滑菜单实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近,由于正在做的一個應用中要用到側滑菜單,所以通過查資料看視頻,學習了一下自定義View,實現一個類似于QQ的側滑菜單,順便還將其封裝為自定義組件,可以實現類似QQ的側滑菜單和抽屜式側滑菜單兩種菜單。

下面先放上效果圖:

我們這里的側滑菜單主要是利用HorizontalScrollView來實現的,基本的思路是,一個布局中左邊是菜單布局,右邊是內容布局,默認情況下,菜單布局隱藏,內容布局顯示,當我們向右側滑,就會將菜單拉出來,而將內容布局的一部分隱藏,如下圖所示:

下面我們就一步步開始實現一個側滑菜單。

一、定義一個類SlidingMenu繼承自HorizontalScrollView

我們后面所有的邏輯都會在這個類里面來寫,我們先寫上其構造方法

public class SlidingMenu extends HorizontalScrollView {/*** 在代碼中使用new時會調用此方法* @param context*/public SlidingMenu(Context context) {this(context, null);}/*** 未使用自定義屬性時默認調用* @param context* @param attrs*/public SlidingMenu(Context context, AttributeSet attrs) {//調用三個參數的構造方法this(context, attrs, 0);}/*** 當使用了自定義屬性時會調用此方法* @param context* @param attrs* @param defStyleAttr*/public SlidingMenu(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);} } 復制代碼

二、定義菜單布局文件

left_menu.xml文件代碼如下

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_centerInParent="true"android:orientation="vertical"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:drawablePadding="20dp"android:layout_marginLeft="20dp"android:gravity="left|center"android:drawableLeft="@mipmap/ic_launcher"android:text="第一個Item"/><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:drawablePadding="20dp"android:layout_marginLeft="20dp"android:gravity="left|center"android:drawableLeft="@mipmap/ic_launcher"android:text="第二個Item"/><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:drawablePadding="20dp"android:layout_marginLeft="20dp"android:gravity="left|center"android:drawableLeft="@mipmap/ic_launcher"android:text="第三個Item"/><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:drawablePadding="20dp"android:layout_marginLeft="20dp"android:gravity="left|center"android:drawableLeft="@mipmap/ic_launcher"android:text="第四個Item"/><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:drawablePadding="20dp"android:layout_marginLeft="20dp"android:gravity="left|center"android:drawableLeft="@mipmap/ic_launcher"android:text="第五個Item"/></LinearLayout> </RelativeLayout> 復制代碼

上面其實就是定義了一列TextView來模仿菜單的Item項

三、定義主布局文件,使用自定義的View

activity_main.xml文件代碼如下

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><!--自定義View--><com.codekong.qq_50_slidingmenu.view.SlidingMenuandroid:layout_width="match_parent"android:layout_height="match_parent"app:rightPadding="100dp"app:drawerType="false"android:scrollbars="none"><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="match_parent"android:orientation="horizontal"><!--引入菜單布局--><include layout="@layout/left_menu"/><!--內容布局--><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/qq_bg"></LinearLayout></LinearLayout></com.codekong.qq_50_slidingmenu.view.SlidingMenu> </RelativeLayout> 復制代碼

四、自定義成員變量

我們定義一些成員變量以便于后面使用

//自定義View布局中內嵌的第一層的LinearLayout private LinearLayout mWapper; //菜單布局 private ViewGroup mMenu; //內容布局 private ViewGroup mContent; //屏幕寬度 private int mScreenWidth; //菜單距屏幕右側的距離,單位dp private int mMenuRightPadding = 50; //菜單的寬度 private int mMenuWidth; //定義標志,保證onMeasure只執行一次 private boolean once = false; //菜單是否是打開狀態 private boolean isOpen = false; 復制代碼

五、拿到屏幕寬度的像素值

因為目前為止,我們沒有使用自定義屬性,所以自定義View默認會調用兩個參數的構造方法,但因為我們第一步中寫構造方法時是在兩個參數的構造方法中調用了三個參數的構造方法,所以,我們將獲取屏幕寬度的代碼寫在三個參數的構造方法中,后面我們自定義屬性后獲取屬性值也是在三個參數的構造方法中書寫相應的邏輯。

/*** 當使用了自定義屬性時會調用此方法* @param context* @param attrs* @param defStyleAttr*/ public SlidingMenu(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);//通過以下步驟拿到屏幕寬度的像素值WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);DisplayMetrics displayMetrics = new DisplayMetrics();windowManager.getDefaultDisplay().getMetrics(displayMetrics);mScreenWidth = displayMetrics.widthPixels; } 復制代碼

六、實現onMeasure()方法

onMeasure()方法是自定義View的正式第一步,它用來決定內部View(子View)的寬和高,以及自身的寬和高,下面是具體的代碼邏輯。

/** * 設置子View的寬和高 * 設置自身的寬和高 * @param widthMeasureSpec * @param heightMeasureSpec */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {if (!once){once = true;mWapper = (LinearLayout) getChildAt(0);mMenu = (ViewGroup) mWapper.getChildAt(0);mContent = (ViewGroup) mWapper.getChildAt(1);//菜單和內容區域的高度都可以保持默認match_parent//菜單寬度 = 屏幕寬度 - 菜單距屏幕右側的間距mMenuWidth = mMenu.getLayoutParams().width = mScreenWidth - mMenuRightPadding;mContent.getLayoutParams().width = mScreenWidth;//當設置了其中的菜單的寬高和內容區域的寬高之后,最外層的LinearLayout的mWapper就自動設置好了}super.onMeasure(widthMeasureSpec, heightMeasureSpec); } 復制代碼

七、實現onLayout()方法

onLayout()方法中主要是確定自定義View中子View放置的位置。下面是具體的代碼。

/*** 通過設置偏移量將Menu隱藏* @param changed* @param l* @param t* @param r* @param b*/ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) {super.onLayout(changed, l, t, r, b);if (changed){//布局發生變化時調用(水平滾動條向右移動menu的寬度,則正好將menu隱藏)this.scrollTo(mMenuWidth, 0);} } 復制代碼

這個比較好理解,由于我們使用的是水平滾動布局,我們默認情況下相當于將水平滾動條向右拖動菜單寬度的的距離,這樣左邊布局的菜單就正好被隱藏了。

八、onTouchEvent()方法

該方法主要處理內部內部View的移動,我們可以在其中寫一些邏輯控制自定義View內部的滑動事件。 由于我們的自定義View是繼承自HorizontalScrollView,我們不再處理按下和移動事件,保持HorizontalScrollView默認的即可,但對于手指抬起事件,我們需要根據手指在水平X軸方向的位移來做出打開菜單或關閉菜單的操作,所以我們的邏輯代碼如下:

@Override public boolean onTouchEvent(MotionEvent ev) {int action = ev.getAction();//按下和移動使用HorizontalScrollView的默認處理switch (action){case MotionEvent.ACTION_UP://隱藏在左邊的位置int scrollX = getScrollX();if (scrollX > mMenuWidth / 2){//隱藏的部分較大, 平滑滾動不顯示菜單this.smoothScrollTo(mMenuWidth, 0);isOpen = false;}else{//完全顯示菜單this.smoothScrollTo(0, 0);isOpen = true;}return true;}return super.onTouchEvent(ev); } 復制代碼

上面最難理解的的就是getScrollX(),它指的是菜單隱藏未顯示的那部分的寬度。關于詳細的解釋,大家可以去看源碼,也可以去看看這篇博客** 圖解Android View的scrollTo(),scrollBy(),getScrollX(), getScrollY()**,講的很清楚。

其實到這一步為止,一個基本的側滑菜單已經做出來了,下面我們將使用屬性動畫對我們的自定義View進行擴展,使其實現最開始展示的抽屜式側滑菜單。

九、屬性動畫實現抽屜式側滑

接下來我們實現抽屜式側滑,抽屜式側滑說白了就是,我們的菜單不是一點點被拉出來,而是看起來菜單就藏在頁面的背后,隨著我們向右滑動,一點點顯露出來。 實現的思路很簡單,當我們拖動時,我們讓菜單布局的偏移量等于getScrollX()的值,也就是時刻把菜單隱藏在左邊的部分向右偏移出來,這樣我們看起來就像菜單藏在頁面后面。如下圖:

當我們左右滑動時會觸發onScrollChanged()方法,我們在此處算出菜單需要的實時的偏移量,然后調用屬性動畫即可。 下面說說具體實現代碼:

/*** 滾動發生時調用* @param l getScrollX()* @param t* @param oldl* @param oldt*/ @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) {super.onScrollChanged(l, t, oldl, oldt);float scale = l * 1.0f / mMenuWidth; //1 ~ 0//調用屬性動畫,設TranslationXmMenu.setTranslationX(mMenuWidth * scale); } 復制代碼

上面方法中的 l 就是上一步中提到的getScrollX()獲得的值。當我們沒有拉菜單時,菜單需要的偏移量就是整個菜單的寬度,當我們將菜單完全拉出時,菜單就不需要偏移量了,此時偏移量為0。此時我們的抽屜式側滑就做好了。

注:此處的屬性動畫是在Android3.0之后引入的,如果需要兼容更早的版本,可以用相關的兼容庫。

十、自定義屬性實現靈活配置

自定義屬性主要是方便使用者可以根據具體的場景實現不同的效果。比如,我們可以通過在xml文件中配置,實現菜單是普通的側滑式還是抽屜式。在剛開始,我們在自定義View中將菜單打開時,菜單右邊緣距離屏幕右邊緣的值設置為50dp,我們通過自定義屬性可以實現在xml文件中自己配置合適的值。

自定義屬性按下面的步驟進行:

1 . 在 res/values 目錄下新建attr.xml文件,文件中寫入的內容如下:

<?xml version="1.0" encoding="utf-8"?> <resources><attr name="rightPadding" format="dimension"/><attr name="drawerType" format="boolean"/><declare-styleable name="SlidingMenu"><attr name="rightPadding"/><attr name="drawerType"/></declare-styleable> </resources> 復制代碼

上面的比較好理解,我們先在上面聲明兩個自定義的屬性的名稱及其對應的類型,然后再在下面的具體的自定義樣式中引用它們。上面兩個自定義的屬性分別是菜單拉開時右邊緣距離屏幕右邊緣的距離,以及菜單是否是抽屜式布局。

2 . 在自定義View類中獲取到自定義的屬性值。如果用戶在xml文件中自定義了屬性值,我們則獲取,如果沒有顯式設置,則使用默認值即可。

順便說一下,前面提到當我們使用自定義屬性時,會默認調用三個參數的構造方法,所以我們獲取自定義屬性值的代碼也是寫在三個參數的構造方法中。

下面是獲取屬性值的代碼:

/*** 當使用了自定義屬性時會調用此方法* @param context* @param attrs* @param defStyleAttr*/ public SlidingMenu(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);//獲取我們自定義的屬性TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs,R.styleable.SlidingMenu, defStyleAttr, 0);int n = typedArray.getIndexCount();//遍歷每一個屬性for (int i = 0; i < n; i++) {int attr = typedArray.getIndex(i);switch (attr){//對我們自定義屬性的值進行讀取case R.styleable.SlidingMenu_rightPadding://如果在應用樣式時沒有賦值則使用默認值50,如果有值則直接讀取mMenuRightPadding = typedArray.getDimensionPixelSize(attr,(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mMenuRightPadding, context.getResources().getDisplayMetrics()));break;case R.styleable.SlidingMenu_drawerType:isDrawerType = typedArray.getBoolean(attr, false);break;default:break;}}//釋放,一定要釋放typedArray.recycle(); } 復制代碼

3 . 上面的代碼中我們已經可以讀取到設置的屬性值,我們可以如下面一樣設置自定義屬性值:

<com.codekong.qq_50_slidingmenu.view.SlidingMenuandroid:layout_width="match_parent"android:layout_height="match_parent"app:rightPadding="100dp"app:drawerType="true"android:scrollbars="none"></com.codekong.qq_50_slidingmenu.view.SlidingMenu> 復制代碼

4 . 使用屬性值控制具體的邏輯,我們的rightPadding一旦獲取到就會在onMeasure()方法中被設置,而drawerType被獲取到就可以控制是否會調用onScrollChanged()中的代碼。代碼如下:

@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {if (!once){once = true;mWapper = (LinearLayout) getChildAt(0);mMenu = (ViewGroup) mWapper.getChildAt(0);mContent = (ViewGroup) mWapper.getChildAt(1);//菜單和內容區域的高度都可以保持默認match_parent//菜單寬度 = 屏幕寬度 - 菜單距屏幕右側的間距mMenuWidth = mMenu.getLayoutParams().width = mScreenWidth - mMenuRightPadding;mContent.getLayoutParams().width = mScreenWidth;//當設置了其中的菜單的寬高和內容區域的寬高之后,最外層的LinearLayout的mWapper就自動設置好了}super.onMeasure(widthMeasureSpec, heightMeasureSpec); } 復制代碼@Override protected void onScrollChanged(int l, int t, int oldl, int oldt) {super.onScrollChanged(l, t, oldl, oldt);if (isDrawerType){float scale = l * 1.0f / mMenuWidth; //1 ~ 0//調用屬性動畫,設TranslationXmMenu.setTranslationX(mMenuWidth * scale);} } 復制代碼

十一、給自定義View設置方法

對于我們的滑動式菜單,我們最常用的功能便是菜單的打開和關閉,所以我們可以在自定義View中定義這兩個方法,方便我們的使用,下面是具體的代碼:

/*** 打開菜單*/ public void openMenu(){if (!isOpen){this.smoothScrollTo(0, 0);isOpen = true;} }/*** 關閉菜單*/ public void closeMenu(){if (isOpen){this.smoothScrollTo(mMenuWidth, 0);isOpen = false;} }/*** 切換菜單*/ public void toggleMenu(){if (isOpen){closeMenu();}else{openMenu();} } 復制代碼

當我們在Activity中使用時可以按下面的代碼使用:

SlidingMenu slidingMenu = (SlidingMenu) findViewById(R.id.sliding_menu); slidingMenu.toggleMenu(); 復制代碼

最后面放上完整的自定義View的代碼:

public class SlidingMenu extends HorizontalScrollView {//自定義View布局中內嵌的最外層的LinearLayoutprivate LinearLayout mWapper;//菜單布局private ViewGroup mMenu;//內容布局private ViewGroup mContent;//屏幕寬度private int mScreenWidth;//菜單距屏幕右側的距離,單位dpprivate int mMenuRightPadding = 50;//菜單的寬度private int mMenuWidth;//定義標志,保證onMeasure只執行一次private boolean once = false;//菜單是否是打開狀態private boolean isOpen = false;//是否是抽屜式private boolean isDrawerType = false;/*** 在代碼中使用new時會調用此方法* @param context*/public SlidingMenu(Context context) {this(context, null);}/*** 未使用自定義屬性時默認調用* @param context* @param attrs*/public SlidingMenu(Context context, AttributeSet attrs) {//調用三個參數的構造方法this(context, attrs, 0);}/*** 當使用了自定義屬性時會調用此方法* @param context* @param attrs* @param defStyleAttr*/public SlidingMenu(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);//獲取我們自定義的屬性TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs,R.styleable.SlidingMenu, defStyleAttr, 0);int n = typedArray.getIndexCount();//遍歷每一個屬性for (int i = 0; i < n; i++) {int attr = typedArray.getIndex(i);switch (attr){//對我們自定義屬性的值進行讀取case R.styleable.SlidingMenu_rightPadding://如果在應用樣式時沒有賦值則使用默認值50,如果有值則直接讀取mMenuRightPadding = typedArray.getDimensionPixelSize(attr,(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mMenuRightPadding, context.getResources().getDisplayMetrics()));break;case R.styleable.SlidingMenu_drawerType:isDrawerType = typedArray.getBoolean(attr, false);break;default:break;}}//釋放typedArray.recycle();//通過以下步驟拿到屏幕寬度的像素值WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);DisplayMetrics displayMetrics = new DisplayMetrics();windowManager.getDefaultDisplay().getMetrics(displayMetrics);mScreenWidth = displayMetrics.widthPixels;}/*** 設置子View的寬和高* 設置自身的寬和高* @param widthMeasureSpec* @param heightMeasureSpec*/@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {if (!once){once = true;mWapper = (LinearLayout) getChildAt(0);mMenu = (ViewGroup) mWapper.getChildAt(0);mContent = (ViewGroup) mWapper.getChildAt(1);//菜單和內容區域的高度都可以保持默認match_parent//菜單寬度 = 屏幕寬度 - 菜單距屏幕右側的間距mMenuWidth = mMenu.getLayoutParams().width = mScreenWidth - mMenuRightPadding;mContent.getLayoutParams().width = mScreenWidth;//當設置了其中的菜單的寬高和內容區域的寬高之后,最外層的LinearLayout的mWapper就自動設置好了}super.onMeasure(widthMeasureSpec, heightMeasureSpec);}/*** 通過設置偏移量將Menu隱藏* @param changed* @param l* @param t* @param r* @param b*/@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {super.onLayout(changed, l, t, r, b);if (changed){//布局發生變化時調用(水平滾動條向右移動menu的寬度,則正好將menu隱藏)this.scrollTo(mMenuWidth, 0);}}@Overridepublic boolean onTouchEvent(MotionEvent ev) {int action = ev.getAction();//按下和移動使用HorizontalScrollView的默認處理switch (action){case MotionEvent.ACTION_UP://隱藏在左邊的位置int scrollX = getScrollX();if (scrollX > mMenuWidth / 2){//隱藏的部分較大, 平滑滾動不顯示菜單this.smoothScrollTo(mMenuWidth, 0);isOpen = false;}else{//完全顯示菜單this.smoothScrollTo(0, 0);isOpen = true;}return true;}return super.onTouchEvent(ev);}/*** 打開菜單*/public void openMenu(){if (!isOpen){this.smoothScrollTo(0, 0);isOpen = true;}}/*** 關閉菜單*/public void closeMenu(){if (isOpen){this.smoothScrollTo(mMenuWidth, 0);isOpen = false;}}/*** 切換菜單*/public void toggleMenu(){if (isOpen){closeMenu();}else{openMenu();}}/*** 滾動發生時調用* @param l getScrollX()* @param t* @param oldl* @param oldt*/@Overrideprotected void onScrollChanged(int l, int t, int oldl, int oldt) {super.onScrollChanged(l, t, oldl, oldt);if (isDrawerType){float scale = l * 1.0f / mMenuWidth; //1 ~ 0//調用屬性動畫,設TranslationXmMenu.setTranslationX(mMenuWidth * scale);}} } 復制代碼

總結

以上是生活随笔為你收集整理的Android自定义View之仿QQ侧滑菜单实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 91香蕉久久| 蜜桃成熟时李丽珍国语 | 午夜视频导航 | 久久久久久久久国产精品一区 | 狠狠干夜夜 | 亚洲一本在线 | 男人喷出精子视频 | 69pao| 亚洲成人中文字幕 | 99re6热在线精品视频播放 | 伊人77| 91性高潮久久久久久久久 | 中文字幕在线欧美 | 国产乱淫av麻豆国产 | 日本高清xxx| 亚洲高清在线免费观看 | 天堂影视av| 91小视频在线 | 中文字幕日韩一区二区三区不卡 | www久久精品 | 国产一级黄色大片 | 中文二区 | 国产成人精品自拍 | av黄色小说 | www.av在线播放 | 99视频国产精品免费观看a | 夜夜嗨一区二区 | 综合久久久久综合 | 成人久久国产 | 热久久中文字幕 | 国产第一页在线播放 | 激情丁香 | 女人的天堂av在线 | 成人三级在线播放 | 免费看的黄色网 | 天天做天天爱天天爽综合网 | 日日摸日日添日日碰9学生露脸 | a级特黄视频 | 69精品久久| 精品国产乱子伦一区二区 | 羞羞的网站在线观看 | 激情综合av | 女女av在线| 69xx网站| 欧美老熟 | 亚洲国产成人在线视频 | 午夜男人天堂 | 国产黄色片免费看 | 日韩免费一区二区 | 涩涩在线播放 | 国产精品无码粉嫩小泬 | 97日韩精品 | 4444亚洲人成无码网在线观看 | 天天夜夜久久 | 天天干狠狠爱 | 内射后入在线观看一区 | 国产精品久久久久久亚洲av | 国产精品国产三级国产aⅴ9色 | 国产精品秘入口18禁麻豆免会员 | 成人国产精品免费观看视频 | 久艹在线观看 | 欧美日韩国产三级 | 无码熟妇人妻av | 成人免费毛片果冻 | 国产a√精品区二区三区四区 | 娇妻玩4p被三个男人伺候电影 | 中文精品在线观看 | 色大师av一区二区三区 | 国内激情自拍 | 久久国产精品国产精品 | 久久99成人 | 四虎看黄 | 亚洲欧美一区二区三区情侣bbw | 日韩av大片 | 国产真实伦对白全集 | 国产成人精品一区二区三区四区 | 污免费在线观看 | 一区二区三区四区视频 | 51嘿嘿嘿国产精品伦理 | 欧美色资源 | 人妻91麻豆一区二区三区 | 老色批影视 | 欧美a∨亚洲欧美亚洲 | 秘密基地免费观看完整版中文 | 91一区二区三区在线 | 91久久综合亚洲鲁鲁五月天 | youjizz.com在线观看 | 欧美在线视频一区二区 | 嫩草研究院在线 | 二区三区在线观看 | 1000部拍拍拍18勿入免费视频 | 老女人综合网 | 禁漫天堂免费网站 | 国产一级片免费 | www亚洲| 久久国产网站 | 午夜污污| 黄色av毛片 | 色视频一区二区 |