您的位置:首页 > 移动开发

ToolBar、TabLayout加角标无从下手?且看一看我的解决方法!

2015-08-28 00:35 471 查看
废话不多,先上个Demo图一探究竟:



①首先说下ToolBar的加角标问题,这是MainActivity的菜单布局:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<item
android:id="@+id/action_cart"
android:title="flashgo"
app:actionLayout="@layout/badge_layout"
app:showAsAction="always"/>
</menu>


如普通的做法不同的是,我们这里使用了

app:actionLayout=”@layout/badge_layout”

这是为了兼容低版本指定一个构建视窗所使用的布局资源,还可以使用actionViewClass实现。

badge_layout布局就是一购物车的图片:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
>
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_centerInParent="true"
android:src="@mipmap/ic_cart"/>
</RelativeLayout>


可能有人这么说,咋不直接android:icon=”@mipmap/ic_cart”呢?多省事啊!

其实一开始我也是这么做的,结果到onCreateOptionsMenu(Menu menu)的时候,通过MenuItem item = menu.findItem(R.id.action_cart)拿到对应的item,

没有getView的方法,只有item.getActionView()或者

MenuItemCompat.getActionView(item)

找不到对象,因为这两个要xml设actionLayout或actionViewClass。

MainActivity的处理方法如下:

private void setUpCartMenuItem(Menu menu) {
MenuItem item = menu.findItem(R.id.action_cart);
View actionView = MenuItemCompat.getActionView(item);
View mCartView = ((ViewGroup) actionView).getChildAt(0);
if (mCartView != null) {
BadgeView badgeView = new BadgeView(MainActivity.this, mCartView);
badgeView.setBadgePosition(BadgeView.POSITION_TOP_RIGHT);
badgeView.setText("0");
mCartView.measure(0, 0);
badgeView.setBadgeMargin(mCartView.getMeasuredWidth() / 55, mCartView.getMeasuredWidth() / 65);
badgeView.show(true);
actionView.measure(0, 0);
}
}


角标的实现是利用Jeff Gilfelt写的BadgeView实现的,原理就是继承TextView,初始化的时候拿到目标View的ViewParent,添加FramLayout,再将目标View和该BadgeView添加到此FramLayout中形成角标的效果,角标可设多个方向。

View actionView = MenuItemCompat.getActionView(item)是兼容到3.0下面的获取actionView的方法,这样子就可以取出View进行加角标操作,而badgeView.setBadgeMargin是因为角标方向跟实际有出入,这样子我们可以设Margin调整至想要的位置。

②接下来说下TabLayout的加角标问题,传统的TabLayout用法是这样的:

mViewPager = (ViewPager) findViewById(R.id.viewpager);
mTabLayout = (TabLayout) findViewById(R.id.tabs);
List<Fragment> fragments = new ArrayList<>();
mTitles = new ArrayList<>();
mTitles.add("时尚");
mTitles.add("复古");
mTitles.add("朋克");
mTitles.add("摇滚");
mTitles.add("嘻哈");
mTitles.add("蓝调");
mTitles.add("爵士");
mTitles.add("古典");
for (String title : mTitles) {
fragments.add(SimpleFragment.newInstance(title));
}
FragmentAdapter adapter = new FragmentAdapter(getSupportFragmentManager(), fragments, mTitles);
mViewPager.setAdapter(adapter);
mTabLayout.setupWithViewPager(mViewPager);


TabLayout的标题的确定是通过mTabLayout.setupWithViewPager(mViewPager)实现的,

源码:

public void setupWithViewPager(@NonNull ViewPager viewPager) {
PagerAdapter adapter = viewPager.getAdapter();
if(adapter == null) {
throw new IllegalArgumentException("ViewPager does not have a PagerAdapter set");
} else {
this.setTabsFromPagerAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(this));
this.setOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager));
if(this.mSelectedTab == null || this.mSelectedTab.getPosition() != viewPager.getCurrentItem()) {
this.getTabAt(viewPager.getCurrentItem()).select();
}

}
}


然后这里调用this.setTabsFromPagerAdapter(adapter);

public void setTabsFromPagerAdapter(@NonNull PagerAdapter adapter) {
this.removeAllTabs();
int i = 0;
for(int count = adapter.getCount(); i < count; ++i) {
this.addTab(this.newTab().setText(adapter.getPageTitle(i)));
}

}


实际上就是去调用adapter.getPageTitle(i)方法,所以使用此TabLayout就要adapter要实现getPageTitle()方法.

然后我们能拿到TabLayout标题的view吗?



很遗憾,还是没有。

不过,TabLayout有TabLayout.Tab.setCustomView(view)的方法,虽然他的TabLayout.Tab.getCustomView()方法修饰符是default的(谷歌我也是醉了),但是我们可以再外面加载布局拿到引用直接加角标了。

方法如下:

private void setUpTabBadge(int position) {
TabLayout.Tab tab = mTabLayout.getTabAt(position);
if (tab != null) {
View view = LayoutInflater.from(this).inflate(R.layout.tab_title_layout, null);
((TextView) view.findViewById(R.id.tv_title)).setText(mTitles.get(position));
tab.setCustomView(view);
BadgeView badgeView = new BadgeView(this, (View) view.getParent());
badgeView.setBadgePosition(BadgeView.POSITION_TOP_RIGHT);
badgeView.setText(position+"");
badgeView.show(true);
}
}


tab_title_layout就是一个TextView

<?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"
android:background="@color/material_transparent">

<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:textColor="@drawable/tab_title_bg"
android:textStyle="bold"/>

</RelativeLayout>


首先拿到对应位置的Tab,然后填充一个布局拿到View引用,

tab.setCustomView(view)设置布局,

此时BadgeView badgeView = new BadgeView(this, (View) view.getParent())的(View) view.getParent()拿到的就是Tab的布局了。

总结:MenuItem和TabLayout加角标的方式都是通过配置一个View,再拿View引用进行角标的设置,因为它们没有提供获取View的方法。这个是我能想到的最好的解决方法了,有更好的可以评论告诉我一下,大家共同进步噻!

附上Demo的资源网址:

http://download.csdn.net/detail/oushangfeng123/9056283
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 布局 menu app