日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

关于 Android 中 TabLayout 下划线适配文字长度解析(附清晰详细的源码解析)

發(fā)布時(shí)間:2024/3/13 Android 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 关于 Android 中 TabLayout 下划线适配文字长度解析(附清晰详细的源码解析) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

溫故而知新 堅(jiān)持原創(chuàng) 請(qǐng)多多支持

一、問題背景

假期在做項(xiàng)目的時(shí)候,當(dāng)時(shí)遇到了一個(gè)需求就是需要使用 TabLayout + ViewPager 來(lái)實(shí)現(xiàn)一個(gè)上部導(dǎo)航欄的動(dòng)態(tài)效果,并且希望下劃線的長(zhǎng)度等于或者小于導(dǎo)航欄中文字的寬度,當(dāng)時(shí)從網(wǎng)上查詢資料的時(shí)候是發(fā)現(xiàn)目前大概是有這么三種思路來(lái)實(shí)現(xiàn),第一種比較簡(jiǎn)單,就是直接通過自定義 CustomView 并在代碼中動(dòng)態(tài)設(shè)置給 Tab 即可,而另一種思路相對(duì)復(fù)雜一些,即利用反射的方式來(lái)進(jìn)行設(shè)置(當(dāng)時(shí)其實(shí)還不太知道可以直接通過 TabLayout.setTabIndicatorFullWidth(false) 來(lái)設(shè)置下劃線寬度等于導(dǎo)航欄中文字的寬度),最后一種方法就是通過直接拷貝一份 TabLayout 代碼并修改其中的部分代碼邏輯(想讓下劃線長(zhǎng)度小于文字長(zhǎng)度好像只有這種辦法)。

但是這三種設(shè)置的方式設(shè)置出來(lái)的效果還是有挺大區(qū)別的,這個(gè)區(qū)別主要體現(xiàn)在動(dòng)畫的效果上面,即通過第一種方式設(shè)置后的下劃線雖然長(zhǎng)度雖然可以同文字相匹配,但是卻喪失了下劃線滑動(dòng)的效果,同時(shí)如果我們需要設(shè)置其長(zhǎng)度與文字的長(zhǎng)度適配等長(zhǎng),那么也意味著對(duì)于不同長(zhǎng)度的文字我們需要編寫特定的 CustomView ,這樣的話其實(shí)工作量和代碼的重復(fù)還是挺高的,但是對(duì)于后二種解決的方案就不存在這種問題。

因?yàn)楫?dāng)時(shí)的項(xiàng)目趕的比較急,并且當(dāng)時(shí)的 Android 方面的基礎(chǔ)也不是特別的扎實(shí),所以當(dāng)時(shí)是在簡(jiǎn)單的嘗試過第二種方式后就選擇放棄了,然后選擇了第一種較為簡(jiǎn)單的實(shí)現(xiàn)方式。后來(lái)發(fā)現(xiàn)之所以網(wǎng)上的代碼不能夠直接拿過來(lái)就是用的原因一方面是隨著 SDK 的不斷更新,不同版本的變量名和一些類名等都已經(jīng)發(fā)生了改變,同時(shí)如果你不是真的理解了其背后的原理,那么只是照搬照抄是無(wú)濟(jì)于事的,因此當(dāng)我在做完項(xiàng)目并通過一定的技術(shù)積累之后,我又返回到了這里,希望能夠通過自己的技術(shù)積累來(lái)解決這個(gè)問題。

因?yàn)榈谝环N方式比較簡(jiǎn)單,所以我就不在這里贅述了,直接分析第二、三種解決這個(gè)問題的方案。同時(shí)本篇文章我將會(huì)從源碼的角度,帶領(lǐng)大家一步一步的從淺到深的去解析 TabLayout 的部分源碼,梳理 TabLayout 背后的代碼邏輯,讓大家能夠更加清晰的真正了解了為什么可以通過反射的方式來(lái)處理這個(gè)問題。

寫這篇文章的目的主要是有兩方面,一方面是因?yàn)楝F(xiàn)在網(wǎng)絡(luò)上有很多的類似博文,但是都已經(jīng)過期了,即其中的很多代碼邏輯已經(jīng)不適用于當(dāng)前的 SDK 版本了,這樣的話其實(shí)反而會(huì)對(duì)初學(xué)者造成一定的誤導(dǎo)和困擾,另一方面,我覺得當(dāng)我們?cè)诮鉀Q一個(gè)問題的時(shí)候,最重要的不是得到解決這個(gè)問題的答案,問題是無(wú)窮無(wú)盡的,答案也是無(wú)窮無(wú)盡的,我覺得更重要的是對(duì)于求解問題過程中我們所能夠?qū)W習(xí)到的更多的東西,以及在這個(gè)過程中對(duì)自己的提升,因?yàn)槲乙步ㄗh大家在看完我的這篇博文之后,自己去點(diǎn)開 TabLayout 的源碼,自己去切身的走一遍解決這個(gè)問題的邏輯,閱讀相關(guān)的代碼。

最后,在開始分析之前,先上圖,第一幅圖是我寒假自己做的一個(gè)學(xué)生課堂狀態(tài)實(shí)時(shí)監(jiān)測(cè)系統(tǒng)的移動(dòng)端,其整個(gè)項(xiàng)目的源碼我已經(jīng)進(jìn)行了開源,其是使用第一種方式來(lái)進(jìn)行實(shí)現(xiàn)的。第二幅圖是我后來(lái)再次自己嘗試,沒有使用?TabLayout.setTabIndicatorFullWidth(false) ,而是通過反射來(lái)達(dá)到的效果。

?

二、源碼解析

(一)結(jié)構(gòu)分析

從這里開始我將帶大家跟隨我探索時(shí)的思路,來(lái)從源碼的角度一步一步的捋清 TabLayout 中部分代碼的邏輯。首先我們需要捋清 TabLayout 視圖的內(nèi)部結(jié)構(gòu),這樣我們才能更加清晰的閱讀后面的源碼。在這里我首先要講的就是關(guān)于 TabLayout 中的三個(gè)比較主要的類,也即 TabLayout 三大內(nèi)部結(jié)構(gòu)。

1)SlidingTabIndicator(繼承自 LinearLayout)

2)TabView(繼承自 LinearLayout)

3)Tab(靜態(tài)內(nèi)部類)

為什么說這三個(gè)類是最主要的類呢,這里我們先通過源碼中的成員變量來(lái)分析一下它們各自的功能。

(1)SlidingTabIndicator

private class SlidingTabIndicator extends LinearLayout {// 下劃線的高度private int selectedIndicatorHeight;// 下劃線的畫筆private final Paint selectedIndicatorPaint;// 默認(rèn)的下劃線private final GradientDrawable defaultSelectionIndicator;int selectedPosition = -1;float selectionOffset;private int layoutDirection = -1;// 下劃線左右坐標(biāo)( 這個(gè)很關(guān)鍵 )private int indicatorLeft = -1;private int indicatorRight = -1;// 下劃線動(dòng)畫private ValueAnimator indicatorAnimator;...}

首先這個(gè)類是繼承自 LinearLayout 的一個(gè) View,同時(shí)它是 TabLayout 的直接子 View,也就是直接位于 TabLayout 下面的子 View,當(dāng)我們閱讀源碼的時(shí)候,我們就會(huì)發(fā)現(xiàn)其實(shí) TabLayout 就是一個(gè) HorizontalScrollView ,因此其是可以進(jìn)行水平滑動(dòng)的,而其只有一個(gè)子 View 即 SlidingTabIndicator 這個(gè) LinearLayout。對(duì)于這點(diǎn),我們先不從源碼探究,先從代碼中來(lái)進(jìn)行簡(jiǎn)單的驗(yàn)證。直接編寫上面這兩句代碼,通過運(yùn)行的結(jié)果我們可以發(fā)現(xiàn) TabLayout 確實(shí)只含有一個(gè)子 View,并且那個(gè)子 View 確實(shí)就是 SlidingTabIndicator。

Log.i("TAB", "The num of tabLayout is " + String.valueOf(mTabLayout.getChildCount())); Log.i("TAB", "The child view is " + String.valueOf(mTabLayout.getChildAt(0).getClass()));

而這個(gè)視圖或者說這個(gè)類的主要作用就是作為一個(gè)底部的容器,裝載著每一個(gè) Item ,這里的 Item 也就是 TabView,其最常見的存在方式就是一行文字或者一行圖片然后加上一個(gè)下劃線,這樣的組合就稱為一個(gè) Item。其次通過上面的成員變量我們還可以獲取到的一個(gè)信息就是,TabView 是僅包含與圖標(biāo)和文字的,并不包含下劃線,下劃線是在 SlidingTabIndicator 中我們通過畫筆畫上去的,因此這個(gè)類其實(shí)也就是我們下面的切入點(diǎn)。

(2)TabView

class TabView extends LinearLayout {// 數(shù)據(jù)存儲(chǔ)private TabLayout.Tab tab;// title and iconprivate TextView textView;private ImageView iconView;// CustomViewprivate View customView;private TextView customTextView;private ImageView customIconView;@Nullableprivate Drawable baseBackgroundDrawable;private int defaultMaxLines = 2;...}

這個(gè)類也是一個(gè)繼承自 LinearLayout 的視圖,同時(shí)它就是我們上面所說的 Item ,作為子項(xiàng)目存在于?SlidingTabIndicator 容器中。通過它的成員變量我們也可以大概了解其作用,首先我們可以發(fā)現(xiàn)它其中會(huì)保存一個(gè) Tab 實(shí)例,這個(gè)實(shí)例的作用主要就是用于存儲(chǔ)圖標(biāo)地址和標(biāo)題等信息,關(guān)于這個(gè)類詳細(xì)講解我們放在下面。接著是一個(gè) TextView 和一個(gè) ImageView ,從變量名我們也可以猜出,它們就是導(dǎo)航欄中的標(biāo)題和圖標(biāo)。再往下的話是 CustomView ,也就是我們?cè)谏厦嫣岬降牡谝环N解決方案中自定義的 CustomView。再往下最后的就是默認(rèn)的背景圖和最大行數(shù)了,這個(gè)暫時(shí)對(duì)我們的用處不太大。

那么 TabView 是在什么時(shí)候被添加到?SlidingTabIndicator 中的呢,當(dāng)我們閱讀源碼的時(shí)候,在前半部分會(huì)發(fā)現(xiàn)下面這樣的一段代碼,我們會(huì)發(fā)現(xiàn)不管是調(diào)用哪個(gè) addTab 方法,最終都會(huì)調(diào)用 configureTab 和 addTabView 這兩個(gè)方法。

public void addTab(@NonNull TabLayout.Tab tab) {this.addTab(tab, this.tabs.isEmpty());}public void addTab(@NonNull TabLayout.Tab tab, int position) {this.addTab(tab, position, this.tabs.isEmpty());}public void addTab(@NonNull TabLayout.Tab tab, boolean setSelected) {this.addTab(tab, this.tabs.size(), setSelected);}public void addTab(@NonNull TabLayout.Tab tab, int position, boolean setSelected) {if (tab.parent != this) {throw new IllegalArgumentException("Tab belongs to a different TabLayout.");} else {this.configureTab(tab, position);this.addTabView(tab);if (setSelected) {tab.select();}}}

所以下面我們?cè)俳又鴣?lái)看這兩個(gè)方法,首先對(duì)于 configureTab 沒什么好說的,就是將當(dāng)前的 tab 保存到 tabs 里面,便于后面的方法調(diào)用(比如外部通過 getTabAt 方法來(lái)獲取指定位置的 Tab),在這個(gè)方法的后面我們看到了 addTabView 方法,我們發(fā)現(xiàn)正是再這個(gè)方法中完成了將當(dāng)前 Item 的 TabView 添加到? 中,而哪個(gè) addView 方法,就已經(jīng)是 ViewGroup 中的方法了。

private void configureTab(TabLayout.Tab tab, int position) {tab.setPosition(position);this.tabs.add(position, tab);int count = this.tabs.size();for(int i = position + 1; i < count; ++i) {((TabLayout.Tab)this.tabs.get(i)).setPosition(i);}}private void addTabView(TabLayout.Tab tab) {TabLayout.TabView tabView = tab.view;this.slidingTabIndicator.addView(tabView, tab.getPosition(), this.createLayoutParamsForTabs());}

(3)Tab

public static class Tab {public static final int INVALID_POSITION = -1;private Object tag;// 圖標(biāo)信息private Drawable icon;// 標(biāo)題信息private CharSequence text;private CharSequence contentDesc;private int position = -1;// customViewprivate View customView;// 記錄TabLayoutpublic TabLayout parent;// 綁定的 TabViewpublic TabLayout.TabView view;...}

?對(duì)于 Tab 類,正如我們上面所說的,他主要是一個(gè)信息存儲(chǔ)的類,并且其會(huì)持有一個(gè) TabView 的引用,這樣的話其實(shí)我們就可以發(fā)現(xiàn) TabView 和 Tab 是互相持有的一個(gè)關(guān)系,TabView 主要負(fù)責(zé)視圖展示,而 Tab 主要負(fù)責(zé)信息的存儲(chǔ)和更新等,類似于 model 和 presenter 的一個(gè)作用。

同時(shí)我們發(fā)現(xiàn)這個(gè)類是一個(gè)靜態(tài)的內(nèi)部類,這也就說明它可以被外部進(jìn)行引用,至于其具體的應(yīng)用如果你仔細(xì)回憶一下就會(huì)想到,當(dāng)我給 TabView 來(lái)設(shè)置視圖的時(shí)候,不管是設(shè)置 TextView 的 text 還是設(shè)置 Icon 還是設(shè)置 CustomView,其實(shí)我們都是先獲取的一個(gè) TabLayout.Tab 對(duì)象,然后來(lái)對(duì)其進(jìn)行操作,當(dāng)數(shù)據(jù)改變后就會(huì)映射到 TabView 上面。所以我們可以理解這個(gè)類主要就是用于開放給用戶來(lái)進(jìn)行相關(guān)的數(shù)據(jù)設(shè)置和更新視圖等。

(4)總結(jié)

所以最后總結(jié)來(lái)說,TabLayout 的結(jié)構(gòu)關(guān)系就是 TabLayout 是最外層的容器,并且是一個(gè)可以支持橫向滑動(dòng)的?HorizontalScrollView ,然后?SlidingTabIndicator 是位于 TabLayout 中的一個(gè)水平的 LinearLayout 容器,所有的 TabView 都是存在于這個(gè)容器之中的,并且我們還可以的到的一個(gè)重要信息就是下劃線是獨(dú)立于 TabView 的,最后對(duì)于 TabView 就是最核心的導(dǎo)航中的單個(gè)子項(xiàng)目,并且是一個(gè) LinearLayout ,同時(shí)其與 Tab 是一種相互持有的關(guān)系,它通過 Tab 來(lái)接受外界對(duì)于視圖中數(shù)據(jù)的更新。

(二)流程分析

介紹完了 TabLayout 的內(nèi)部結(jié)構(gòu),接下來(lái)我們就來(lái)梳理在 TabLayout 中,下劃線到底是怎樣來(lái)設(shè)置的。為了便于讀者理解,所以這里我采用和我當(dāng)時(shí)分析時(shí)相同的逆推的分析方式,從后向前對(duì)其進(jìn)行推導(dǎo)。

首先我們開始的時(shí)候如果毫無(wú)頭緒,這里我提供一個(gè)思路,就是我們可以先從外界找一個(gè)入口,比如通過 TabLayout.setSelectTabIndicatorColor 這個(gè)設(shè)置下劃線顏色的方式開始來(lái)進(jìn)入到下劃線的相關(guān)設(shè)置代碼中。這個(gè)方法的代碼很清晰,它直接調(diào)用了 slidingTabIndicator 的 setSelectedIndicator 方法,因此我們直接跟進(jìn)去。

public void setSelectedTabIndicatorColor(@ColorInt int color) {this.slidingTabIndicator.setSelectedIndicatorColor(color);}

進(jìn)到這個(gè)方法里面我們會(huì)發(fā)現(xiàn)這里就沒有什么營(yíng)養(yǎng)了,它只是簡(jiǎn)單的調(diào)用的畫筆的顏色設(shè)置方法,但是在這里我們得到了一個(gè)新的思路,也就是我們大概可以明白原來(lái)下劃線是通過這個(gè) selectedIndicatorPaint 畫筆畫出來(lái)的,這樣我們就可以去選擇跟蹤這個(gè)畫筆。?

void setSelectedIndicatorColor(int color) {if (this.selectedIndicatorPaint.getColor() != color) {this.selectedIndicatorPaint.setColor(color);ViewCompat.postInvalidateOnAnimation(this);}}

因?yàn)橥ㄟ^上面的代碼,我們基本已經(jīng)可以確定下劃線的繪制是在?selectedIndicatorPaint 中完成的了并且其是一個(gè) LinearLayout,所以我們直接從這個(gè)視圖的 onMeasure 來(lái)捋順邏輯。

對(duì)于 onMeasure 方法我們可以發(fā)現(xiàn)它大概的測(cè)量流程是這樣的,首先其通過調(diào)用父類(LinearLayout)的 onMeasure 方法來(lái)對(duì)其子 View(TabView)來(lái)進(jìn)行遞歸測(cè)量,其次其通過遍歷求取列表中的 TabView 的最寬寬度并保存,然后它又通過一個(gè)遍歷將列表中所有的 TabView 的寬度都設(shè)定為最大值,最后進(jìn)行重繪。

其實(shí)從下面的主要流程我們已經(jīng)可以明白為什么 TabLayout 中所有的 TabView 的寬度都是相同的了,接著我們繼續(xù)往下走。?

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// 1.測(cè)量子視圖super.onMeasure(widthMeasureSpec, heightMeasureSpec);if (MeasureSpec.getMode(widthMeasureSpec) == 1073741824) {if (TabLayout.this.mode == 1 && TabLayout.this.tabGravity == 1) {int count = this.getChildCount();int largestTabWidth = 0;int gutter = 0;// 2.獲取列表中最大的寬度f(wàn)or(int z = count; gutter < z; ++gutter) {View child = this.getChildAt(gutter);if (child.getVisibility() == 0) {largestTabWidth = Math.max(largestTabWidth, child.getMeasuredWidth());}}if (largestTabWidth <= 0) {return;}gutter = TabLayout.this.dpToPx(16);boolean remeasure = false;if (largestTabWidth * count > this.getMeasuredWidth() - gutter * 2) {TabLayout.this.tabGravity = 0;TabLayout.this.updateTabViews(false);remeasure = true;} else {// 3.通過遍歷將所有的 TabView 的寬度都設(shè)置為最大寬度f(wàn)or(int i = 0; i < count; ++i) {android.widget.LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams)this.getChildAt(i).getLayoutParams();if (lp.width != largestTabWidth || lp.weight != 0.0F) {lp.width = largestTabWidth;lp.weight = 0.0F;remeasure = true;}}}// 4.如果求得新的最大寬度則重新測(cè)量所有 TabViewif (remeasure) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);}}}}

接下來(lái)被調(diào)用的就應(yīng)該是 onLayout 布局方法,這個(gè)方法的主要作用就是對(duì)已經(jīng)測(cè)量好的視圖進(jìn)行布局放置,從源碼中我們可以看到,它依然先調(diào)用了父類的 onLayout 方法來(lái)對(duì)其列表中的 TabView 來(lái)進(jìn)行遞歸布局放置,然后其判斷了當(dāng)前視圖是正在播放動(dòng)畫,如果在播放動(dòng)畫就停止通話后再調(diào)用方法進(jìn)行布局。

這里其實(shí)我們通過上下兩個(gè)方法的名稱已經(jīng)可以明白,其實(shí)這個(gè)當(dāng)前類重寫的就是對(duì)于下劃線的布局放置,并且上面的 animateIndicatorToPosition 方法就是對(duì)于下劃線動(dòng)畫的設(shè)置,而下面的 updateIndicatorPostion 方法就是對(duì)于下劃線的一個(gè)布局放置了,所以我們直接跟進(jìn)下面的方法。

protected void onLayout(boolean changed, int l, int t, int r, int b) {super.onLayout(changed, l, t, r, b);if (this.indicatorAnimator != null && this.indicatorAnimator.isRunning()) {this.indicatorAnimator.cancel();long duration = this.indicatorAnimator.getDuration();this.animateIndicatorToPosition(this.selectedPosition, Math.round((1.0F - this.indicatorAnimator.getAnimatedFraction()) * (float)duration));} else {this.updateIndicatorPosition();}}

?對(duì)于這個(gè)?updateIndicatorPosition 方法整個(gè)流程是稍微有一點(diǎn)復(fù)雜,但是我們需要看比較主要的部分,即當(dāng)不設(shè)置偏移和自定義 CustomView 的情況下,這時(shí)的話正常來(lái)說 selectedTitle 應(yīng)該是 TabView 類型的,并且當(dāng)前 left 和 right 就應(yīng)當(dāng)是 selectedTitle 的 left 和 right 坐標(biāo),也就是 TabView 的左右坐標(biāo),也就是說默認(rèn)情況下下劃線的寬度會(huì)等于 TabView 的寬度。最后再通過?setIndicatorPosition 方法將求得左右坐標(biāo)值賦給下劃線的左右坐標(biāo),并刷新視圖。

這里需要強(qiáng)調(diào)的是我們可以在外界通過 TabLayout.setTabIndicatorFullWidth 這個(gè)方法來(lái)將?tabIndicatorFullWidth 設(shè)置為 false,這時(shí)的下劃線模式就會(huì)按照 TabView 中文字的長(zhǎng)度來(lái)設(shè)置了,所以我們接下來(lái)可以看一下這里面的?calculateTabViewContentBounds 方法的具體實(shí)現(xiàn),看看它是怎么做的。

private void updateIndicatorPosition() {// 獲取當(dāng)前被選中的子項(xiàng)目View selectedTitle = this.getChildAt(this.selectedPosition);int left;int right;if (selectedTitle != null && selectedTitle.getWidth() > 0) {// 獲取被選中子項(xiàng)目的左右坐標(biāo)left = selectedTitle.getLeft();right = selectedTitle.getRight();// 如果當(dāng)前視圖的 tabIndicatorFullWidth 被設(shè)置為 true(默認(rèn)為 true)// 同時(shí)當(dāng)前子項(xiàng)目是 TabView 類型的if (!TabLayout.this.tabIndicatorFullWidth && selectedTitle instanceof TabLayout.TabView) {// 調(diào)用方法重新計(jì)算子項(xiàng)目的左右坐標(biāo)this.calculateTabViewContentBounds((TabLayout.TabView)selectedTitle, TabLayout.this.tabViewContentBounds);left = (int)TabLayout.this.tabViewContentBounds.left;right = (int)TabLayout.this.tabViewContentBounds.right;}// 如果設(shè)置了偏移量并且當(dāng)前所選中的子項(xiàng)目有效// 那么再次重新計(jì)算左右坐標(biāo)值if (this.selectionOffset > 0.0F && this.selectedPosition < this.getChildCount() - 1) {// 獲取下個(gè)項(xiàng)目的信息View nextTitle = this.getChildAt(this.selectedPosition + 1);int nextTitleLeft = nextTitle.getLeft();int nextTitleRight = nextTitle.getRight();// 這一步的判斷同上if (!TabLayout.this.tabIndicatorFullWidth && nextTitle instanceof TabLayout.TabView) {this.calculateTabViewContentBounds((TabLayout.TabView)nextTitle, TabLayout.this.tabViewContentBounds);nextTitleLeft = (int)TabLayout.this.tabViewContentBounds.left;nextTitleRight = (int)TabLayout.this.tabViewContentBounds.right;}// 計(jì)算左右坐標(biāo)// 公式中拋去偏移量其實(shí)也就是前一個(gè)的的坐標(biāo)加上left = (int)(this.selectionOffset * (float)nextTitleLeft + (1.0F - this.selectionOffset) * (float)left);right = (int)(this.selectionOffset * (float)nextTitleRight + (1.0F - this.selectionOffset) * (float)right);}} else {right = -1;left = -1;}this.setIndicatorPosition(left, right);}void setIndicatorPosition(int left, int right) {if (left != this.indicatorLeft || right != this.indicatorRight) {this.indicatorLeft = left;this.indicatorRight = right;ViewCompat.postInvalidateOnAnimation(this);}}

我們可以看到,這里它先通過 getContentWidth 方法獲取了內(nèi)容的寬度,然后獲取內(nèi)容的中心,并設(shè)置下下劃線的左右坐標(biāo)分別為中心點(diǎn)向左向右分別增加內(nèi)容寬度的一半,這樣也就實(shí)現(xiàn)了下劃線和標(biāo)題文字寬度相等的目的。

private void calculateTabViewContentBounds(TabLayout.TabView tabView, RectF contentBounds) {int tabViewContentWidth = tabView.getContentWidth();if (tabViewContentWidth < TabLayout.this.dpToPx(24)) {tabViewContentWidth = TabLayout.this.dpToPx(24);}int tabViewCenter = (tabView.getLeft() + tabView.getRight()) / 2;int contentLeftBounds = tabViewCenter - tabViewContentWidth / 2;int contentRightBounds = tabViewCenter + tabViewContentWidth / 2;contentBounds.set((float)contentLeftBounds, 0.0F, (float)contentRightBounds, 0.0F);}private int getContentWidth() {boolean initialized = false;int left = 0;int right = 0;View[] var4 = new View[]{this.textView, this.iconView, this.customView};int var5 = var4.length;for(int var6 = 0; var6 < var5; ++var6) {View view = var4[var6];if (view != null && view.getVisibility() == 0) {left = initialized ? Math.min(left, view.getLeft()) : view.getLeft();right = initialized ? Math.max(right, view.getRight()) : view.getRight();initialized = true;}}return right - left;}

最后我們來(lái)看一下 draw 方法,在這個(gè)方法中下劃線完成了最后的繪制。對(duì)于 draw 這個(gè)方法沒有什么太多需要講的,與正常視圖的 draw 方法的區(qū)別不大,需要注意的就是它是通過 Drawable.setBounds 這個(gè)方法來(lái)完成繪制的,對(duì)于這個(gè)方法作用就是繪制一個(gè)指定區(qū)域內(nèi)的矩形。這樣的話其實(shí)也就為我們提供了一個(gè)思路,那就是直接通過這個(gè)方法來(lái)設(shè)置我們想要的下劃線長(zhǎng)度。

public void draw(Canvas canvas) {int indicatorHeight = 0;if (TabLayout.this.tabSelectedIndicator != null) {indicatorHeight = TabLayout.this.tabSelectedIndicator.getIntrinsicHeight();}if (this.selectedIndicatorHeight >= 0) {indicatorHeight = this.selectedIndicatorHeight;}int indicatorTop = 0;int indicatorBottom = 0;// 下劃線模式判斷switch(TabLayout.this.tabIndicatorGravity) {case 0:// 默認(rèn)是位于 TabView 的底部的indicatorTop = this.getHeight() - indicatorHeight;indicatorBottom = this.getHeight();break;case 1:indicatorTop = (this.getHeight() - indicatorHeight) / 2;indicatorBottom = (this.getHeight() + indicatorHeight) / 2;break;case 2:indicatorTop = 0;indicatorBottom = indicatorHeight;break;case 3:indicatorTop = 0;indicatorBottom = this.getHeight();}// 如果下劃線左坐標(biāo)大于零并且右坐標(biāo)大于左坐標(biāo)// 說明當(dāng)前的下劃線坐標(biāo)合法有效if (this.indicatorLeft >= 0 && this.indicatorRight > this.indicatorLeft) {Drawable selectedIndicator = DrawableCompat.wrap((Drawable)(TabLayout.this.tabSelectedIndicator != null ? TabLayout.this.tabSelectedIndicator : this.defaultSelectionIndicator));// 繪制下劃線selectedIndicator.setBounds(this.indicatorLeft, indicatorTop, this.indicatorRight, indicatorBottom);if (this.selectedIndicatorPaint != null) {if (VERSION.SDK_INT == 21) {selectedIndicator.setColorFilter(this.selectedIndicatorPaint.getColor(), android.graphics.PorterDuff.Mode.SRC_IN);} else {DrawableCompat.setTint(selectedIndicator, this.selectedIndicatorPaint.getColor());}}selectedIndicator.draw(canvas);}super.draw(canvas);}}

三、解決方案

對(duì)于不同的情況有不同的解決方案,如果你僅僅是需要下劃線的長(zhǎng)度等于文字的長(zhǎng)度,以前的話是只能通過反射來(lái)進(jìn)行設(shè)置,而現(xiàn)在的話可以直接通過?TabLayout.setTabIndicatorFullWidth(false) 這個(gè)方法來(lái)進(jìn)行設(shè)置,并且對(duì)于其原理我們也已經(jīng)進(jìn)行過了相應(yīng)的分析。

如果你需要下劃線的長(zhǎng)度小于文字的長(zhǎng)度的話,那么暫時(shí)還沒有太好的解決方案,這里提供一個(gè)思路,因?yàn)樵创a是不允許修改的,我們可以拷貝一份,然后對(duì)其進(jìn)行修改,然后再進(jìn)行替換。至于修改的方法其實(shí)就是我們上面最后提到的 draw 中的?Drawable.setBounds 方法,通過它來(lái)直接將我們?cè)O(shè)置的下劃線長(zhǎng)度設(shè)置給下劃線。

但是需要注意的是,我們必須要先獲取 TabView 的水平中點(diǎn),然后再?gòu)闹悬c(diǎn)分別向兩側(cè)延長(zhǎng)二分之一長(zhǎng)度的設(shè)置值,這么做是為了保證下劃線位于 TabView 的水平中心處。具體的代碼邏輯如下,直接重寫?SlidingTabIndicator 的 draw 方法中這部分的邏輯即可(新增的代碼就是我添加注釋下面的兩行)。

if (this.indicatorLeft >= 0 && this.indicatorRight > this.indicatorLeft) {Drawable selectedIndicator = DrawableCompat.wrap((Drawable)(TabLayout.this.tabSelectedIndicator != null ? TabLayout.this.tabSelectedIndicator : this.defaultSelectionIndicator));// 求 TabView 的水平中心點(diǎn)后并繪制下劃線int indictorCenter = (this.indicatorLeft+this.indicatorRight)/2;selectedIndicator.setBounds( indictorCenter-indictorWidth/2, indicatorTop, indictorCenter+indictorWidth/2, indicatorBottom);if (this.selectedIndicatorPaint != null) {if (VERSION.SDK_INT == 21) {selectedIndicator.setColorFilter(this.selectedIndicatorPaint.getColor(), android.graphics.PorterDuff.Mode.SRC_IN);} else {DrawableCompat.setTint(selectedIndicator, this.selectedIndicatorPaint.getColor());}}selectedIndicator.draw(canvas);

最后我們還需要給外界留一個(gè)方法,使用戶可以從外界對(duì)下劃線的長(zhǎng)度進(jìn)行設(shè)置(這個(gè)方法設(shè)置在 SlidingTabIndicator 類外部就可以了)。

int indictorWidth = 0;public int getIndictorWidth() {return indictorWidth;}public void setIndictorWidth(int indictorWidth) {this.indictorWidth = dpToPx(indictorWidth);}

?

總結(jié)

以上是生活随笔為你收集整理的关于 Android 中 TabLayout 下划线适配文字长度解析(附清晰详细的源码解析)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

国产精品美女 | 狠狠网站| 欧美激精品| 久久精品中文视频 | 欧美片网站yy | 在线观看国产区 | 99久久精品日本一区二区免费 | 日韩影视在线观看 | 久久福利综合 | 00av视频| 中文字幕在线色 | 国内精品久久久久久久久久清纯 | 日本精品一区二区三区在线观看 | 97超碰人人澡人人 | 五月婷婷伊人网 | 成 人 黄 色 视频 免费观看 | 国产精品99久久久精品 | 久久久资源网 | 中文字幕乱码一区二区 | 国产免费久久精品 | 国内免费久久久久久久久久久 | 成人久久亚洲 | 日韩精品中文字幕av | 亚洲欧美va | 69久久久久久久 | 成人亚洲欧美 | 国产精品9区 | 69xxxx欧美 | 国产网站在线免费观看 | 国产高清视频免费最新在线 | 亚洲在线视频免费 | av 一区二区三区 | 精品久久久久久久久久久院品网 | 久久色在线观看 | 毛片美女网站 | 欧美在线视频一区二区 | 欧美久久九九 | av一级片在线观看 | 国产一区二区免费 | 天天干天天操av | 亚洲一级理论片 | 国产99久久 | www.香蕉视频 | 久草爱| 亚洲免费在线观看视频 | 久久久亚洲电影 | 日韩精品一区在线播放 | 精品99在线观看 | 黄色av观看| 欧美 日韩 国产 中文字幕 | 91视频在线免费 | 中文资源在线播放 | 免费电影一区二区三区 | 九九有精品| 一区二区三区四区在线 | 久久成人18免费网站 | 国产人成精品一区二区三 | 午夜精品在线看 | 久久国产免费 | 久草在线一免费新视频 | 91精品导航 | adc在线观看 | 午夜精品福利一区二区 | 日韩av成人在线观看 | 欧美日韩一区二区在线观看 | 最近中文字幕高清字幕在线视频 | 精品一区在线看 | 免费在线观看的av网站 | 天天干 夜夜操 | 欧美成天堂网地址 | 日韩素人在线观看 | 中文字幕在线观看一区二区 | 国产精品久久久区三区天天噜 | 日日夜日日干 | 操处女逼 | 国产精品第72页 | 天天摸天天舔天天操 | 日日操天天射 | 日韩欧美在线播放 | 在线黄色国产 | 中文字幕国语官网在线视频 | 97日日碰人人模人人澡分享吧 | 九色视频网址 | 国产精品18久久久久久首页狼 | 国产91对白在线播 | 91看片看淫黄大片 | 亚欧洲精品视频在线观看 | 97在线视频免费看 | 天堂视频中文在线 | 免费看毛片网站 | 亚洲激情p| 91亚洲视频在线观看 | 免费av网址大全 | 996久久国产精品线观看 | 亚洲1区 在线 | 久久手机看片 | 国产精品久久久久影院日本 | 97人人超 | www.天天操 | 四虎永久精品在线 | 欧美福利网址 | 久久香蕉影视 | 久久精品99久久久久久2456 | 亚洲国产精品视频在线观看 | 最近中文字幕大全中文字幕免费 | 亚色视频在线观看 | 国产乱对白刺激视频不卡 | 91视频首页 | 欧美视频99 | 国产美女视频网站 | 97成人在线观看视频 | 香蕉视频91 | 国产一级免费av | 99久高清在线观看视频99精品热在线观看视频 | www.亚洲黄色 | 日日夜夜天天操 | 91精品国产一区二区三区 | 国产一区私人高清影院 | 免费观看黄色12片一级视频 | 91黄视频在线观看 | 日本久久免费电影 | 婷婷色网视频在线播放 | 欧美性脚交 | 天堂视频一区 | 久久久www成人免费精品张筱雨 | 免费看的视频 | 亚洲精品视频在线观看视频 | 18女毛片| 婷婷黄色片 | 一区二区中文字幕在线 | 欧美成人精品在线 | 日韩电影在线一区 | 色视频网站免费观看 | 免费精品视频在线 | 免费中文字幕 | 久草精品在线播放 | 国产96在线观看 | 在线免费观看视频一区 | 国产一区二区精品久久 | 毛片视频电影 | 九月婷婷色| 欧美成人黄色 | 日韩欧美精品一区 | 日韩va欧美va亚洲va久久 | 国产精品第一页在线 | 日韩色区 | 久久爽久久爽久久av东京爽 | 久久精品精品电影网 | 国产人成一区二区三区影院 | 国产精品五月天 | 美女黄网站视频免费 | 国内精品在线看 | 69精品人人人人 | 在线看黄网站 | 亚洲国产日韩一区 | 久久国产精品久久久久 | 国产九色在线播放九色 | 午夜色婷婷 | 黄色电影小说 | 国产在线一区观看 | 精品国产乱码久久久久 | 又黄又爽免费视频 | 欧美日性视频 | 中文字幕精品一区久久久久 | 欧洲精品二区 | 黄色免费网战 | 欧美视频国产视频 | 欧美日韩视频在线一区 | 中文字幕精品www乱入免费视频 | 久久国产精品一区二区三区四区 | 成人av电影免费在线播放 | 91精品办公室少妇高潮对白 | 欧美一区二区三区特黄 | 国产高清av免费在线观看 | 手机看片国产日韩 | 亚洲视频999 | 97影视| 色com网 | 丁香六月激情婷婷 | av在线免费观看黄 | 色婷婷狠 | 天天天天综合 | 国内精品久久久久影院一蜜桃 | 亚洲韩国一区二区三区 | 免费手机黄色网址 | 一区二精品 | 五月天国产 | 国产高清在线不卡 | 中文字幕在线观看视频网站 | 在线中文字幕视频 | 337p西西人体大胆瓣开下部 | 三级视频日韩 | 视频国产在线观看18 | 欧美大片在线观看一区 | 亚洲电影一区二区 | 久久国产精品99久久久久久老狼 | 97超碰色 | 91免费的视频在线播放 | 亚洲精品在线二区 | 五月天.com | 天天舔夜夜操 | www操操| 青青草在久久免费久久免费 | 国产精品毛片一区二区三区 | 国产精品一区二区三区四区在线观看 | 久久久精品电影 | 日韩av电影国产 | 午夜精品视频一区 | 日韩电影一区二区三区 | 国产精品女人久久久久久 | 亚洲国产手机在线 | 91麻豆精品国产自产在线 | 久久久麻豆视频 | 青青色影院| 久久国产免费 | 亚洲一区二区三区毛片 | av国产网站| 丁香婷婷深情五月亚洲 | 欧美一级黄色网 | 伊人午夜视频 | 欧洲成人av | av在线一二三区 | 亚洲一区二区三区在线看 | 国产不卡在线 | 久久精品专区 | 日日夜夜噜 | av中文字幕在线看 | 亚洲一区天堂 | 日韩精品在线视频 | 日韩不卡高清视频 | 色九九影院 | 三上悠亚一区二区在线观看 | 日韩在线视频二区 | 青春草免费视频 | 国产很黄很色的视频 | 96精品视频 | 久草在线视频在线 | 99色亚洲 | 成人久久免费 | 国产免费av一区二区三区 | 干天天| 国产中文字幕视频在线 | 五月婷婷一区二区三区 | 91香蕉视频在线下载 | 国产精品久久 | 久久久国产精品网站 | 四虎成人网 | 国产一区二区三区高清播放 | 中文理论片 | 国产一二三四在线观看视频 | 2020天天干夜夜爽 | 黄色.com| 亚洲综合成人专区片 | 日韩在线免费小视频 | 97超碰色| 97香蕉久久超级碰碰高清版 | 成在线播放 | 在线观看av小说 | 欧美午夜激情网 | 国产精品99久久久久的智能播放 | 亚洲理论电影网 | 四虎天堂 | 欧洲精品码一区二区三区免费看 | av一二三区 | 免费视频在线观看网站 | 国产 日韩 中文字幕 | 日韩精品一区二区三区高清免费 | 黄色av高清 | 少妇精品久久久一区二区免费 | 久久精品观看 | 亚洲欧美国产日韩在线观看 | 国产精品毛片久久久久久久 | 综合久久久久久久久 | 国产精品一区二区无线 | www免费| 欧美精品午夜 | 欧美激情第28页 | 色婷婷av国产精品 | 天堂网一区二区三区 | 大型av综合网站 | 91漂亮少妇露脸在线播放 | 国产专区欧美专区 | 国产精品理论在线观看 | 日韩高清不卡一区二区三区 | 中文字幕在线看视频国产 | 国产在线a| 久艹视频免费观看 | 亚洲成人资源在线 | 欧美一级片免费在线观看 | 日韩69av | 精品国产资源 | 免费在线观看黄色网 | 婷婷99 | 日韩在线视频国产 | 97免费在线视频 | 国产高清免费在线观看 | 涩涩网站在线看 | 精品一区二三区 | 91视频大全| 天天射天天拍 | 久热色超碰| 香蕉视频在线网站 | 亚洲国产午夜 | 久草视频在线资源站 | 在线 视频 亚洲 | 1024手机看片国产 | 国产福利91精品一区二区三区 | 91色影院| 欧美激情综合五月色丁香小说 | 久久综合福利 | 精品久久一区二区三区 | 爱av在线网 | 91中文字幕视频 | 69视频在线播放 | 午夜精品区 | 久久综合狠狠综合 | 一区二区三区四区五区在线 | av中文字幕在线播放 | 99久精品视频 | 久久精品超碰 | 六月色丁香| 亚洲国产中文字幕 | 久久网页| 免费在线观看的av网站 | 日韩在线观看高清 | 黄色片视频免费 | 国产在线观看 | 一区二区三区日韩精品 | 国产精品亚洲a | 在线观看黄 | 天堂在线一区 | 在线免费中文字幕 | 日韩三级中文字幕 | 日韩一三区 | 99热九九这里只有精品10 | 国产一区二区免费看 | 91精品啪| 欧美va日韩va | 在线观看黄色国产 | aaaaaa毛片| 国产高潮久久 | 狠狠色丁香婷婷综合久小说久 | 在线久久| 午夜久久福利影院 | 五月天网站在线 | 欧美精品久久99 | 久久久久久国产一区二区三区 | 久久视频网 | 色爽网站 | 国产成人久久久久 | 亚洲精品乱码久久久久久蜜桃不爽 | 久九视频 | 精品国产区 | 久久伊人操 | 亚洲精品国产成人 | 天天综合中文 | 精品美女久久久久 | 国产精品资源在线观看 | 精品视频在线免费 | 最新av电影网站 | 人人躁| 高清国产在线一区 | 欧美成人精品欧美一级乱黄 | 色a资源在线 | www在线观看国产 | av资源免费看 | 亚洲a成人v | 久久久久久国产精品亚洲78 | 96国产精品视频 | 日本精品一二区 | 美女黄视频免费 | 有码视频在线观看 | 九九热只有这里有精品 | 五月婷婷爱 | 精品国产乱码久久久久久1区二区 | 伊人超碰在线 | 日韩精品一区在线播放 | 国产系列 在线观看 | www.狠狠色.com | 国产精品视频免费看 | 人人澡人人草 | 欧美一区二区视频97 | 激情六月婷婷久久 | 久久精品视频免费 | 97在线精品| 国产精品久久久久免费a∨ 欧美一级性生活片 | 在线а√天堂中文官网 | 夜夜躁狠狠躁日日躁视频黑人 | 欧美一级在线观看视频 | 国产精品999久久久 久产久精国产品 | 在线精品一区二区 | 四虎影视4hu4虎成人 | 天天操天天添 | 色国产在线 | 日日爽夜夜爽 | 午夜视频色 | 国产一级在线看 | 色姑娘综合 | 精品久久久久久国产偷窥 | 色在线视频 | 久草在线观看 | 亚洲国产网址 | 久久99操| 日韩福利在线观看 | 去干成人网| 欧美亚洲一区二区在线 | 欧美做受高潮电影o | 丁香花在线视频观看免费 | 日韩欧美一区二区三区视频 | 98涩涩国产露脸精品国产网 | 免费在线国产 | 91tv国产成人福利 | 97日日碰人人模人人澡分享吧 | 蜜桃视频精品 | 国产精品久久视频 | 久久av不卡 | 91精品对白一区国产伦 | 久久久久免费精品视频 | 免费亚洲片 | 韩国av永久免费 | 日本黄色免费网站 | 美女黄濒 | 午夜男人影院 | 在线国产视频观看 | 成人免费视频播放 | 欧美激情综合五月色丁香 | 国产色一区 | 色天堂在线视频 | 日本高清dvd | 久久 国产一区 | 在线电影91 | 日韩欧美黄色网址 | 日韩av网址在线 | 亚洲精品日韩av | 激情影院在线观看 | 国产精品大片在线观看 | www178ccom视频在线 | 日韩有码在线播放 | 中文字幕在线观看国产 | 久久韩国免费视频 | 天天看天天操 | 精品在线视频观看 | 国产成人一级 | 麻豆视频大全 | 色插综合 | 这里只有精品视频在线观看 | 国产日韩精品在线 | 国产精品第一 | 午夜久久精品 | 亚洲精品高清视频 | 深夜免费福利网站 | 国产精品久久久久一区二区三区 | 99精品视频精品精品视频 | a天堂一码二码专区 | 日本高清中文字幕有码在线 | 96超碰在线 | 国产成人久久精品 | 午夜日b视频 | 久久免费国产精品1 | 欧美a视频在线观看 | 最近高清中文字幕在线国语5 | 国产精品久久久久一区二区 | 99精品视频在线观看免费 | 青青河边草免费直播 | 五月激情亚洲 | 日韩久久精品一区 | av色图天堂网| 欧美色噜噜噜 | 亚洲一区av | 亚洲国产日韩av | 丰满少妇高潮在线观看 | avcom在线| 亚洲精品黄色 | 人人干在线 | 日韩一级片网址 | 国产精品久久99综合免费观看尤物 | 日本久久综合网 | 激情综合啪 | 91在线播放视频 | 九九久久影院 | 国产午夜小视频 | 激情综合婷婷 | 日韩欧美综合 | 天天操操 | 中文字幕av免费观看 | 色婷在线 | 在线视频 一区二区 | 久久成 | 国产亚洲精品久久久久久久久久久久 | 亚洲高清在线精品 | 在线香蕉视频 | 久久综合色一综合色88 | 伊人一级 | 国产精品一区二区三区电影 | 麻豆传媒电影在线观看 | 亚洲va男人天堂 | 天天干天天摸 | 国产小视频免费在线网址 | 亚洲理论在线观看电影 | 免费a网址| 日韩av在线一区二区 | 天天搞夜夜骑 | av在线免费网 | 国产一二三区av | 欧美日韩在线看 | 九色免费视频 | 亚洲最大av网 | 国产黄色精品在线 | 亚洲伊人天堂 | 中文字幕乱视频 | 中文字幕国产一区 | 9ⅰ精品久久久久久久久中文字幕 | 日韩在线视频网 | 午夜国产一区二区 | 在线成人性视频 | 在线直播av | 中文字幕第一页在线 | 天天色天天综合 | 午夜精品视频在线 | 成人黄色电影在线 | 热久久免费视频 | 久久久av电影 | 91看片淫黄大片在线播放 | 美女免费视频一区二区 | 国产区第一页 | 国产免费久久久久 | av在线看网站 | 国产成人91 | 99re久久精品国产 | 欧洲精品视频一区二区 | 免费在线播放黄色 | 丰满少妇久久久 | 亚洲经典在线 | 久久综合九色综合97_ 久久久 | 国产精品久久久久久久久久新婚 | 日韩成人不卡 | 欧美 激情在线 | 综合久久网站 | 日本成址在线观看 | 日韩欧美在线播放 | 久久久免费 | 久操视频在线 | 日韩在线观看视频一区二区三区 | 在线草| 欧洲性视频 | 五月婷综合网 | 国产九九精品视频 | 最近中文字幕完整高清 | 久草在在线| 久久99国产精品视频 | 亚洲国产播放 | www.亚洲精品| 欧美日本不卡视频 | 国产伦精品一区二区三区四区视频 | 亚洲欧美视屏 | 国产爽视频 | 少妇bbb搡bbbb搡bbbb | 2021av在线| 色噜噜色噜噜 | 免费高清国产 | 国产99久久久欧美黑人 | 免费黄色一区 | 成人黄色片在线播放 | 亚洲涩涩涩 | 黄色av网站在线观看免费 | 91免费试看 | 一区二区三区在线观看 | 色综合亚洲精品激情狠狠 | 在线播放精品一区二区三区 | a级国产乱理论片在线观看 伊人宗合网 | 久久草网站 | 国产91在线观 | 五月婷婷开心 | 91大神精品视频在线观看 | 91探花国产综合在线精品 | 在线视频一区二区 | 精品久久久久免费极品大片 | 欧美性粗大hdvideo | 日韩电影在线观看中文字幕 | 午夜在线观看影院 | 97热视频 | 日韩av视屏在线观看 | 国产成人在线看 | 免费成人在线电影 | www.天天干.com | 91在线精品视频 | 国产免费又爽又刺激在线观看 | 天天干天天摸天天操 | 黄色大全免费网站 | 毛片美女网站 | 中国一级特黄毛片大片久久 | 久久国产一二区 | 免费看的视频 | 天干啦夜天干天干在线线 | 中文字幕观看av | 欧美射射射 | 国产精品18毛片一区二区 | 国产成人av电影在线观看 | 人人玩人人弄 | 成人午夜电影网站 | 午夜久草 | av电影一区二区 | 粉嫩av一区二区三区四区五区 | 99精品视频免费全部在线 | 97超碰国产精品女人人人爽 | 九九三级毛片 | 久久久久久蜜桃一区二区 | 国产成人高清 | 亚洲电影图片小说 | 色综合中文字幕 | 色综合亚洲精品激情狠狠 | 久在线观看| 免费在线一区二区 | 久久成 | 亚洲国产日韩在线 | 91久久精品日日躁夜夜躁国产 | 成人欧美亚洲 | 欧美色精品天天在线观看视频 | 日韩激情视频在线 | 亚洲aⅴ免费在线观看 | 久99久精品视频免费观看 | 久久人人看 | 久久久综合电影 | 国产精品久久久久高潮 | 一区二区av | 久久久久久精 | 在线观看一级 | 五月天亚洲精品 | 91精品小视频 | 中文字幕乱码电影 | 91成人在线视频观看 | 国产一二三在线视频 | 狠狠久久婷婷 | 香蕉视频在线免费看 | 狠狠色狠狠色综合日日小说 | 久久久久成人精品免费播放动漫 | 婷婷丁香狠狠爱 | 色爱成人网 | 91精品视频一区二区三区 | 日韩精品视频免费专区在线播放 | av大片网站 | 在线导航av | 婷婷在线不卡 | 伊人日日干 | 国产麻豆精品一区二区 | 四虎成人精品永久免费av | 中文字幕免费 | 国产精品毛片久久 | 中文字幕一区二区三区四区视频 | 玖玖在线观看视频 | 久久久国产精品一区二区三区 | 99免费精品视频 | 亚洲精品综合欧美二区变态 | 黄在线免费看 | 亚洲国产午夜精品 | 正在播放久久 | 久久96| 麻豆一精品传二传媒短视频 | 日韩av线观看 | 成人资源在线播放 | 久久精品超碰 | 悠悠av资源片| 91丨九色丨蝌蚪丰满 | 99视频在线观看一区三区 | 丁香在线观看完整电影视频 | 天天综合狠狠精品 | 日韩中文字幕免费视频 | av在线进入 | 亚洲每日更新 | 色婷婷综合五月 | 国产精品久久久久久久av大片 | 一级精品视频在线观看宜春院 | 天堂网一区二区 | 91精品久久久久久综合乱菊 | 天天操天天色综合 | 久久综合婷婷国产二区高清 | 在线天堂亚洲 | 亚洲japanese制服美女 | 久久热亚洲 | 五月天综合网站 | 丁香婷婷激情啪啪 | 黄色国产高清 | 少妇超碰在线 | 久久久精品久久日韩一区综合 | 中文字幕黄色 | 在线三级av | 黄色小视频在线观看免费 | 综合激情婷婷 | 日韩一二区在线观看 | av电影在线免费观看 | 欧美激情精品一区 | 久久久久久久久久久精 | 久久在现 | 97狠狠操| 很黄很污的视频网站 | 黄色小说在线免费观看 | 国产精品s色 | 免费观看十分钟 | 欧美影院久久 | 欧美激情综合五月 | 国产美腿白丝袜足在线av | 久久人视频| 久久毛片视频 | bbw av| 日韩午夜av电影 | 久久婷婷一区 | 久草资源在线观看 | 97成人免费视频 | 91在线免费播放视频 | 国产午夜免费视频 | 一区二区理论片 | 丝袜精品视频 | 国产在线a免费观看 | 婷婷视频在线播放 | 久久久精品免费看 | 特级西西人体444是什么意思 | 国产精品一区二区三区免费视频 | 成人av免费在线播放 | 丁香花在线视频观看免费 | 久久久久久片 | 精品欧美小视频在线观看 | 国产精品理论片 | 色综合久久久久综合体桃花网 | 正在播放 久久 | 中文字幕在线日本 | 久久伊人精品天天 | 欧美激情综合五月 | 日本不卡一区二区三区在线观看 | 久久成人18免费网站 | 91夜夜夜| 欧美福利视频 | 九九久| 国产又粗又硬又爽视频 | 日本精品一区二区在线观看 | 狠狠色狠狠色综合系列 | 色91在线视频 | 人人添人人澡人人澡人人人爽 | 国产91国语对白在线 | 91免费看黄色 | 精品一区二区三区四区在线 | 亚洲视频在线观看 | 久久久国产精品网站 | 九九久久成人 | 91看国产| 九精品| 97精品国产97久久久久久免费 | 91亚洲精品在线 | 欧美日韩在线观看一区 | 亚洲国产免费网站 | av色影院 | 午夜成人免费影院 | 黄色片网站av | 91精品国产自产在线观看 | 亚洲视频h| 福利电影一区二区 | 亚洲成av人片在线观看 | 国产精品高清免费在线观看 | 国产精品久久久99 | 911国产精品 | 欧美成人日韩 | 最新国产精品拍自在线播放 | 九九色综合 | 婷婷色在线播放 | 精品产品国产在线不卡 | 久久国产精品99久久久久久老狼 | 激情综合色综合久久综合 | 久久久久久毛片精品免费不卡 | 日本最大色倩网站www | 日本xxxxav| 国产91亚洲精品 | 天天爽天天碰狠狠添 | 久久精品国产一区二区电影 | 国产91学生粉嫩喷水 | 午夜精品久久久久99热app | 91精品视频免费看 | 97超碰人人澡人人爱学生 | 亚洲精品视频在线观看免费 | 在线观看中文字幕一区 | 日韩精品一区二区在线 | 日韩欧美亚州 | 免费看污黄网站 | 成人黄色小说视频 | 国产极品尤物在线 | 国产亚洲一区二区在线观看 | 五月天国产| 久久久国产成人 | 97超碰国产精品女人人人爽 | 国产色视频网站2 | 香蕉在线播放 | 色多多污污在线观看 | 91成年人视频 | 丁香花五月 | 久久精品视频网址 | 天天综合网天天综合色 | 天天鲁天天干天天射 | 国产精品久久久久久久久久久不卡 | 国产精品入口传媒 | 中文字幕国产一区二区 | 丁香婷婷色月天 | 免费观看一级成人毛片 | 欧美成亚洲 | 中文永久字幕 | 久久综合视频网 | 91精品久久香蕉国产线看观看 | 一区二区视频在线免费观看 | 免费高清在线观看电视网站 | 亚洲一级片 | 国产精品第十页 | 视频一区二区在线观看 | 国产精品毛片完整版 | 99久久毛片 | 96亚洲精品久久 | 在线色吧 | 色综合中文字幕 | 91在线一区 | 狠狠狠狠狠狠狠狠干 | 亚洲视频国产 | 久久天堂影院 | 激情久久五月天 | www国产亚洲精品久久网站 | 欧美大jb | 亚洲视频精品在线 | 在线观看免费福利 | 97日日碰人人模人人澡分享吧 | 亚洲午夜精品一区二区三区电影院 | 不卡av电影在线 | 美女免费视频一区 | 免费福利视频网站 | 国产高清久久久久 | 激情欧美网| 久久精品电影 | 国产精品视频免费在线观看 | 婷婷新五月 | 国产.精品.日韩.另类.中文.在线.播放 | 久草在线欧美 | 久久久综合 | 亚洲精品中文字幕在线 | 日韩av图片| 在线观看福利网站 | 免费成人黄色 | 成人97视频一区二区 | 精品黄色在线观看 | 草免费视频 | 欧美在线资源 | 免费观看xxxx9999片 | 69视频国产 | 热久久免费视频精品 | 综合网天天 | 亚洲天天干 | 天天操婷婷| 国产视频久久久 | 99色99| 欧美精品久久天天躁 | 国产经典 欧美精品 | 日韩精品视频在线免费观看 | 欧美一区视频 | 欧亚日韩精品一区二区在线 | 99精品一区二区 | 久草视频在线新免费 | www.狠狠操.com | 九九九免费视频 | 蜜臀av在线一区二区三区 | 国产高清视频在线播放一区 | 波多野结衣理论片 | av在线电影网站 | 国产高清精品在线观看 | 超碰公开在线观看 | 中文字幕在线精品 | 欧美日韩高清一区二区 国产亚洲免费看 | 在线观看av免费观看 | 97超碰总站| 久久99国产精品二区护士 | 中文字幕在线字幕中文 | 国产欧美在线一区二区三区 | 日韩精品在线看 | 国产成人精品久久久久蜜臀 | av一区二区三区在线 | 欧美日韩另类在线观看 | 国产亚洲视频在线免费观看 | 美州a亚洲一视本频v色道 | 99中文字幕 | 天天操天天射天天操 | 日韩欧美在线一区 | 四虎国产精品成人免费影视 | 久久国产精品一区二区三区四区 | 日本久久91 | 国产精品福利无圣光在线一区 | 成年人视频在线 | 国产亚洲一区 | 蜜臀久久99精品久久久久久网站 | 97超碰人人澡人人爱学生 | 国产亚洲va综合人人澡精品 | 五月天婷婷免费视频 | 91精品国产成人www | 色婷婷88av视频一二三区 | 欧美性春潮 | 在线观看黄污 | 韩日精品视频 | 伊人狠狠操 | 婷婷亚洲激情 | 四虎永久精品在线 | 亚洲国产中文字幕 | www.久久视频 | 久草在线资源观看 | 黄污网| 日韩午夜在线播放 | 国产色在线观看 | 免费观看一区 | 最近高清中文在线字幕在线观看 | 中文字幕 欧美性 | 亚洲一区av | 国产精品a久久 | 在线小视频你懂得 | 在线观看免费版高清版 | 久久视频6 | 亚洲午夜电影网 | 成人在线观看资源 | 日日夜夜人人天天 | 久久爽久久爽久久av东京爽 | 国产精品久久久久久久久久久久午夜片 | 涩涩网站在线 | 久久久www成人免费毛片麻豆 | 天天操天天操天天操天天操 | 特级毛片在线 | 午夜精品视频免费在线观看 | 日韩三级.com | 欧美激情综合五月 | 亚洲欧洲精品视频 | 丁香婷婷深情五月亚洲 | 五月激情丁香图片 | 奇米影视在线99精品 | 精品uu| 免费黄色av | 黄网站污| 麻豆免费观看视频 | 国产亚洲va综合人人澡精品 | 丁香激情综合 | 99久久电影 | 国产一级91 | 久久精品屋 | 青青久草在线视频 | 99久久网站 | 日韩三级视频在线观看 | 欧美成人69av| 不卡av在线播放 | 香蕉手机在线 | 亚洲精品视频在线观看免费视频 | 亚洲欧美国产精品久久久久 | 91精品导航 | 在线视频久 | 五月天久久久久久 | 波多野结衣电影一区二区 | 亚洲精品小区久久久久久 | 91在线影院 | 黄色片网站av | 久久久久久久久电影 | 久久久天堂| 黄色小视频在线观看免费 | 91麻豆网| 国产精品a久久久久 | 亚洲国产免费看 | 精品一区二区免费在线观看 | 97超碰中文字幕 | 六月天色婷婷 | 天躁狠狠躁 | 亚洲国产经典视频 | av 一区二区三区 | 国产成人久久av977小说 | 色网站在线看 | 97免费视频在线 | 亚洲最大的av网站 | 黄色免费观看视频 | 国产黄| 日日夜夜精品视频天天综合网 | 成人黄色大片网站 | 天天干,天天射,天天操,天天摸 | 黄色国产高清 | 激情片av| 天天综合91 | 国产免费久久久久 | 欧美日韩午夜爽爽 | 在线免费观看成人 | 亚洲人在线视频 | 国产一级一级国产 | 成人av一区二区在线观看 | 丁香婷婷亚洲 | av在线一二三区 | 在线观看的a站 | 波多野结衣在线播放视频 | 色婷婷激情电影 | 久久精品网站免费观看 | 人人澡人人爽欧一区 | 免费日韩 精品中文字幕视频在线 | 国产又粗又猛又黄又爽的视频 | 国产精品自在线拍国产 | 欧美另类高清 | 成人午夜影院 | 成人中文字幕+乱码+中文字幕 |