美文网首页Android开发经验谈Android实用技术
2019日更挑战(四),简单方便的TabLayout

2019日更挑战(四),简单方便的TabLayout

作者: Jlanglang | 来源:发表于2019-01-04 22:07 被阅读88次

瞎扯

连更了3天文章,还是有压力的,没什么时间准备,只有晚上有时间写写.

内容不太好想,太简单的写起来没意思,太复杂的一下写不明白.哈哈

感觉自己想的太多了,想有顺序,渐进式的把知识总结出来.
还是想到什么写什么吧.

继续瞎扯

为什么要挑战日更呢,因为一段时间我手上都没android项目做了.如果再不写东西回忆总结一下.肯定都忘了.

TabLayout

这是一个5.0 以后出来的Material Design控件.

其主要作用就是显示标签.

这玩意出来之前,主要是用TabHost.作用基本差不多.
已经完全被Tablayout取代了

能实现的效果.

基本就这几种了.

1.头部标签

#

一般Tablayout会配合ViewPager使用.

关键方法:

 TabLayout.setupWithViewPager(viewPager);

内部实现也简单,大致就是ViewPage和Tablayout互相绑定.
互相监听,页码切换回调.


当然.不配合Viewpager也可以单独使用.
不过,自己创建标签的话,会发现创建方式有点独特.

  Tab tab = tabLayout.newTab();
   tab.setText(text);//设置文字
   tab.setIcon(img);//设置图标
   tabLayout.add(tab);
  @NonNull
    public Tab newTab() {
        Tab tab = sTabPool.acquire();
        if (tab == null) {
            tab = new Tab();
        }
        tab.mParent = this;
        tab.mView = createTabView(tab);
        return tab;
    }

    public static final class Tab {

         ....//省略

        Tab() {
            // Private constructor
        }

一个内部类,然后不公开构造函数.属性都被隐藏限制了.

后面吐槽下这个控件的缺点.

2.底部导航

image.png

我记得,15年的时候,实现这个效果,多数人还是用的RadioButton和RadioGroup.
也有用TabHost的.

现在,这种,其实用这个Tablayout就可以了


首先

Tablayout会有个指示器(下面的线),所以要把这个线隐藏起来.

tabIndicatorHeight="0dp"//这样就可以了

然后

必须设置自定义的View当做Tab的内容,自带的是搞不定的.要弄也贼麻烦.

tab.setCustomView(inflate);

好在这个控件还是考虑了完全自定义扩展.不然这个控件真的很鸡肋了.
剩下的就不用说了.设置进去的view制定样式就好了.

选中tab

image.png

其实这个呢,也是可以用tablayout写的.哈哈.
也是把下面的线隐藏,然后设置

 tablayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
                @Override
                public void onTabSelected(TabLayout.Tab tab) {
                      //这个是选中是的回调.
                }

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

                }

                @Override
                public void onTabReselected(TabLayout.Tab tab) {
                      //这个方法就是选中后再次点击的回调,所以可以实现上面的效果
                }
            });

说说缺点!

缺点真的是很多,但还是阻止不了我经常用它.

1.拿不到控件.

image.png

这点真的很操蛋,你会发现.你除了设置参数外.拿不到任何东西.

  public static final class Tab {

        /**
         * An invalid position for a tab.
         *
         * @see #getPosition()
         */
        public static final int INVALID_POSITION = -1;

        private Object mTag;
        private Drawable mIcon;
        private CharSequence mText;
        private CharSequence mContentDesc;
        private int mPosition = INVALID_POSITION;
        private View mCustomView;

        TabLayout mParent;//包内可见
        TabView mView;//包内可见

都是不公开的.

有办法拿吗?

有! 反射

等你反射拿到了TabView了以后.

    class TabView extends LinearLayout {
        private Tab mTab;
        private TextView mTextView;
        private ImageView mIconView;

        private View mCustomView;
        private TextView mCustomTextView;
        private ImageView mCustomIconView;

        private int mDefaultMaxLines = 2;

        public TabView(Context context) {
            super(context);
            if (mTabBackgroundResId != 0) {
                ViewCompat.setBackground(
                        this, AppCompatResources.getDrawable(context, mTabBackgroundResId));
            }
            ViewCompat.setPaddingRelative(this, mTabPaddingStart, mTabPaddingTop,
                    mTabPaddingEnd, mTabPaddingBottom);
            setGravity(Gravity.CENTER);
            setOrientation(VERTICAL);
            setClickable(true);
            ViewCompat.setPointerIcon(this,
                    PointerIconCompat.getSystemIcon(getContext(), PointerIconCompat.TYPE_HAND));
        }

你会发现,你还是啥也拿不到,还得再反射一次!这就操蛋了.


最后发现就只有一个getCustomVIew方法.
但是这个方法是获取你设置进去的自定义View的.
所以.如上面说的,想改样式.

那就

tab.setCustomView(inflate);

2.线条

线条默认是满格的! 也就是你的Tab有多宽,线条就有多长.要想改线的长度.
一个办法!.反射!
所以github上就出现了一些自定义的TabLayout.
还是挺好用的.实在要做一些TabLayout做不了的效果,建议还是用开源的控件.不要去反射改,不稳定.
这里就不列出来.github搜TabLayout.就能找到.

3.写死的bottomMargin

 static final int DEFAULT_GAP_TEXT_ICON = 8; // 这个常量值.

private void updateTextAndIcon(@Nullable final TextView textView,
             ...//省略
            if (iconView != null) {
                MarginLayoutParams lp = ((MarginLayoutParams) iconView.getLayoutParams());
                int bottomMargin = 0;
                if (hasText && iconView.getVisibility() == VISIBLE) {
                    // If we're showing both text and icon, add some margin bottom to the icon
                    //看这里,就是这一句,这个写死的margin.8dp!!!!!!!!!
                    bottomMargin = dpToPx(DEFAULT_GAP_TEXT_ICON);
                }
                if (bottomMargin != lp.bottomMargin) {
                    lp.bottomMargin = bottomMargin;
                    iconView.requestLayout();
                }
            }
             ...
        }

总结

总的来说,Tablayout是个很简单的控件.非常容易使用,api不是很多.
配合ViewPager使用非常方便.
它的缺点,更像是故意而为止,为了安全或者规范?也也许吧


日更第4天,哈哈,明天应该不写控件.

您的喜欢与回复是我最大的动力-_-
交流群:493180098

相关文章

网友评论

    本文标题:2019日更挑战(四),简单方便的TabLayout

    本文链接:https://www.haomeiwen.com/subject/wzbqrqtx.html