成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

TabLayout的簡單運用和若干問題的解決

PiscesYE / 1514人閱讀

摘要:初步實現(xiàn)之前在知乎上看到有人對微信的設(shè)計改動將使用頻率高的朋友圈消息提醒和公眾號這三個功能獨立出來放在首頁。

1、介紹和準備

我們在使用手機App時不難會看到這樣的頁面上面是一組起導航作用的標簽,點擊標簽就會切換到相應的頁面;在不同的頁面中滑動時,標簽的樣式(文字大小或者顏色)也會發(fā)生變化。這樣你任何時候都能一眼看出自己停留在哪個頁面。這個布局出鏡率實在太高了,我甚至敢說每個學Android的人都寫過這樣的布局(下面就是知乎中的頁面)。

好了,廢話少說,我們照例先來分析一下這個布局的組成。標簽下面的頁面比較容易想到:整體是一個左右滑動的ViewPager,每一頁則可以用Fragment填充,也就是ViewPager+Fragment。但上面的標簽部分就有點頭大了,之前我們都是使用第三方的項目(如PagerSlidingTabStrip),高手的話也可以自定義一個控件。但是這樣并非長久之計,所以谷歌后來人性化地推出了自家的標簽控件TabLayout(注意可不要跟TableLayout搞混了,后者是Android的基本布局之一,而前者是一個控件)。TabLayout顧名思義就是包含Tab的布局,它包含在Design support library庫中,要使用它,你需要在先添加依賴庫:

我導入的是最新的26.0.0版本:

compile "com.android.support:design:26.0.0-alpha1"

準備完這些,我們可以開始寫代碼了。

2、初步實現(xiàn)

之前在知乎上看到有人對微信的設(shè)計改動:將使用頻率高的朋友圈、消息提醒和公眾號這三個功能獨立出來放在首頁。我很贊同這樣的設(shè)計思路,所以今天就來弄一個簡陋版的吧。大體效果如下:

2.1 頁面布局


    

    

    

上面的TabLayout的高度固定為60dp,然后讓ViewPager占據(jù)剩余的空間即可?,F(xiàn)在我來介紹一下用到的TabLayout的屬性:

app:tabIndicatorColor:標簽下面移動的橫線的顏色。

app:tabTextColor:標簽文字的顏色

app:tabSelectedTextColor :標簽被選中后的文字顏色

TabLayout還有很多其他的屬性,比如你要是不想要下面的移動橫線的話,可以調(diào)用屬性app:tabIndicatorHeight ,將高度設(shè)置為0dp即可。關(guān)于TabLayout的其他屬性,大家可以看看這篇博客,動手練習一下:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0731/3247.html

2.2 創(chuàng)建Viewpager頁面(Fragment)

為了能夠識別我們切換到的是ViewPager的哪個頁面,我們在Fragment中創(chuàng)建一個帶參數(shù)的構(gòu)造函數(shù),動態(tài)添加一個TextView,它的文本內(nèi)容跟標簽的一致就好。

public class TabFragment extends Fragment {
    private Context context;
    private String content; //Fragment的顯示內(nèi)容
    public TabFragment() {

    }

    public TabFragment(Context context,String content){
        this.context = context;
        this.content = content;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        TextView textView = new TextView(context);
        textView.setText(content);
        textView.setTextSize(30);
        textView.setGravity(Gravity.CENTER);
        return textView;
    }
}
2.3 MainActivity代碼

先來看代碼:

public class MainActivity extends AppCompatActivity {
    private ViewPager viewPager;
    private TabLayout tabLayout;
    private List fragments = new ArrayList<>();
    private List tabs = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        initView();
    }

    private void initData() {
        tabs.add("新消息");
        tabs.add("朋友圈");
        tabs.add("公眾號");
        fragments.add(new TabFragment(this,tabs.get(0)));
        fragments.add(new TabFragment(this,tabs.get(1)));
        fragments.add(new TabFragment(this,tabs.get(2)));
    }

    private void initView() {
        tabLayout = (TabLayout) findViewById(R.id.tayLayout);
        viewPager = (ViewPager) findViewById(R.id.viewPager);
        //設(shè)置TabLayout的模式
        tabLayout.setTabMode(TabLayout.MODE_FIXED);
        viewPager.setAdapter(new TabAdapter(getSupportFragmentManager()));
        //關(guān)聯(lián)ViewPager和TabLayout
        tabLayout.setupWithViewPager(viewPager);
    }

    class TabAdapter extends FragmentPagerAdapter{
        public TabAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            return fragments.get(position);
        }

        @Override
        public int getCount() {
            return fragments.size();
        }
        
        //顯示標簽上的文字
        @Override
        public CharSequence getPageTitle(int position) {
            return tabs.get(position);
        }
    }
}

代碼不長,initData方法中添加數(shù)據(jù),initView方法初始化控件,跟我們平時使用ViewPager的寫法差別不大。要注意的是TabLayout需要設(shè)置模式(即setTabMode方法),一共有兩種:

TabLayout.MODE_FIXED :當Tab較少,且占滿整個屏幕時可以使用這種模式;

TabLayout.MODE_SCROLLABLE :當Tab數(shù)量較多,屏幕寬度不夠時使用該模式,整個TabLayout是可以左右滑動的。

除此之外,我們需要讓Tab顯示文字,要重寫FragmentPagerAdapter的getPageTitle方法,返回每一個Tab的文字內(nèi)容。最后可別忘了最關(guān)鍵的一步:使用setupWithViewPager方法關(guān)聯(lián)Viewpager和TabLayout,這樣兩者才會聯(lián)動。

運行一下,就可以看到動態(tài)圖中的效果了。

3、進階 3.1 修改標簽字體大小

默認的Tab字體大小有點小,看起來不太舒服,當我們?nèi)バ薷淖煮w大小時卻發(fā)現(xiàn),TabLayout居然沒有提供跟TextSize相關(guān)的屬性。不過不用急,TabLayout其實提供了一個更靈活的屬性app:tabTextAppearance ,它可以修改字體的樣式,從而間接修改字體的大小。

我們在style.xml中自定義一個樣式,繼承于TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse ,在屬性android:textSize中設(shè)置我們想要的字體大小,這里我設(shè)為20sp。

      

接下來在布局文件中使用就可以了。

運行一下,這下看起來清楚多了。

3.2 添加分割線

TabLayout的標簽之間是默認沒有分割線的,如果我們想添加分割線,讓標簽之間更有層次感的話,可以添加以下的代碼:

        //設(shè)置分割線
        LinearLayout linearLayout = (LinearLayout) tabLayout.getChildAt(0);
        linearLayout.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
        linearLayout.setDividerDrawable(ContextCompat.getDrawable(this,
                R.drawable.divider)); //設(shè)置分割線的樣式
        linearLayout.setDividerPadding(dip2px(10)); //設(shè)置分割線間隔

自定義的分割線樣式:



    
    

setDividerPadding方法中輸入的參數(shù)是單位是px,我們需要轉(zhuǎn)換成像素:

    //像素單位轉(zhuǎn)換
    public int dip2px(int dip) {
        float density = getResources().getDisplayMetrics().density;
        return (int) (dip * density + 0.5);
    }
3.2 顯示信息數(shù)目

現(xiàn)在我們來嘗試一下這樣的效果:將tab的文字分為兩行,第二行顯示信息的數(shù)目,當然,我們并沒有真的信息,所以直接輸入一些假數(shù)據(jù)就可以。為了讓文字變?yōu)閮尚校覀兛梢约尤霌Q行符。

        tabs.add("新消息"+"
"+999);
        tabs.add("朋友圈"+"
"+99);
        tabs.add("公眾號"+"
"+9);

運行,發(fā)現(xiàn)文字確實分成了兩行。但是等等,怎么文字大小小了那么多?

如果你查一下TabLayout的源碼,就會發(fā)現(xiàn)這一切早就命中注定了。源碼中有這么一段:

               if (mIconView != null && mIconView.getVisibility() == VISIBLE) {
                    // If the icon view is being displayed, we limit the text to 1 line
                    maxLines = 1;
                } else if (mTextView != null && mTextView.getLineCount() > 1) {
                    // Otherwise when we have text which wraps we reduce the text size
                    textSize = mTabTextMultiLineSize;
                }

這里是設(shè)置Tab的icon和字體大小的,在else if代碼塊中,我們發(fā)現(xiàn)了,當TextView的文本大于一行時,就會強制使用特定的字體(textSize = mTabTextMultiLineSize),這就解釋了為什么我們的字體設(shè)置不奏效了。

那么,我們該怎么辦呢?

3.3 自定義標簽

條條大路通羅馬,TabLayout早就給我們準備了另一條路了,那就是自定義標簽布局。(溫馨提示:下面的代碼對之前的改動較大,大家可能會覺得之前做的都是無用功,但是凡事總是循序漸進的,請不必灰心。)

自定義標簽布局



    

    

這里我們用到了一個選擇器,代碼如下:

標簽顏色選擇器


    
    
在代碼中實現(xiàn)
    /**
     * 設(shè)置Tab的樣式
     */
        private void setTabView() {
        holder = null;
        for (int i = 0; i < tabs.size(); i++) {
            //依次獲取標簽
            TabLayout.Tab tab = tabLayout.getTabAt(i);
            //為每個標簽設(shè)置布局
            tab.setCustomView(R.layout.tab_item);
            holder = new ViewHolder(tab.getCustomView());
            //為標簽填充數(shù)據(jù)
            holder.tvTabName.setText(tabs.get(i));
            holder.tvTabNumber.setText(String.valueOf(tabNumbers.get(i)));
            //默認選擇第一項
            if (i == 0){
                holder.tvTabName.setSelected(true);
                holder.tvTabNumber.setSelected(true);
                holder.tvTabName.setTextSize(18);
                holder.tvTabNumber.setTextSize(18);
            }
        }

        //tab選中的監(jiān)聽事件
        tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                holder = new ViewHolder(tab.getCustomView());
                holder.tvTabName.setSelected(true);
                holder.tvTabNumber.setSelected(true);
                //選中后字體變大
                holder.tvTabName.setTextSize(18);
                holder.tvTabNumber.setTextSize(18);
                //讓Viewpager跟隨TabLayout的標簽切換
                viewPager.setCurrentItem(tab.getPosition());

            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
                holder = new ViewHolder(tab.getCustomView());
                holder.tvTabName.setSelected(false);
                holder.tvTabNumber.setSelected(false);
                //恢復為默認字體大小
                holder.tvTabName.setTextSize(16);
                holder.tvTabNumber.setTextSize(16);
            }

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

            }
        });
    }

    class ViewHolder{
        TextView tvTabName;
        TextView tvTabNumber;

        public ViewHolder(View tabView) {
            tvTabName = (TextView) tabView.findViewById(R.id.tv_tab_name);
            tvTabNumber = (TextView) tabView.findViewById(R.id.tv_tab_number);
        }
    }

創(chuàng)建一個setTabView方法來設(shè)置Tab的樣式,在for循環(huán)中為每一個標簽創(chuàng)建布局。setCustomView方法可以設(shè)置Tab的布局,getCustomView則可以獲取當前Tab的布局。

我們既然使用的是自定義的布局,那么選中時的樣式也要手動設(shè)置了。跟ViewPager類似,TabLayout也有自己的選中監(jiān)聽事件(addOnTabSelectedListener)。在標簽被選中時將狀態(tài)設(shè)置為選中,并切換到相應的ViewPager頁面,未選中的頁面則將選中狀態(tài)設(shè)為false即可。

補充一點,選中Tab后字體變大這一功能是我后面加上去的,所以代碼只在GitHub中更新了。由于屬性android:textSize 不支持drawable文件,所以這里不能用狀態(tài)選擇器,但好在代碼里實現(xiàn)也不復雜,就不必過多解釋了。

4、開拓思維

既然TabLayout如此貼心地給我們提供了自定義標簽布局的方法,那么我們就要好好利用它,比如除了文字之外,我們還可以添加圖片,讓標簽頁的內(nèi)容更加豐富。另外,TabLayout不一定非要放在頂部,也可以放在底部,去掉下劃線之后就可以實現(xiàn)與RadioGroup一樣的效果。

最后,是說好的源碼了:
CSDN
GitHub

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/67124.html

相關(guān)文章

  • TabLayout使用遇到坑及方案

    摘要:但對于我們的對于界面還原度要求較高,對于之間的間距也有一些要求,所以也要處理,對于間距部分的處理可以按照之前的方式通過反射來完成。注意,這種方式因為需要計算的文字寬度,所以要放到設(shè)置完所有的后調(diào)用。 修改下劃線寬度的坑 效果如下: showImg(https://s2.ax1x.com/2019/04/18/ES2KYV.png); 代碼實現(xiàn)方式: 如果想要實現(xiàn)這種效果,最主要控制的就...

    baishancloud 評論0 收藏0

發(fā)表評論

0條評論

PiscesYE

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<