瞎扯
连更了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
网友评论