ToolBar、TabLayout加角标无从下手?且看一看我的解决方法!
2015-08-28 00:35
471 查看
废话不多,先上个Demo图一探究竟:
①首先说下ToolBar的加角标问题,这是MainActivity的菜单布局:
如普通的做法不同的是,我们这里使用了
app:actionLayout=”@layout/badge_layout”
这是为了兼容低版本指定一个构建视窗所使用的布局资源,还可以使用actionViewClass实现。
badge_layout布局就是一购物车的图片:
可能有人这么说,咋不直接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的处理方法如下:
角标的实现是利用Jeff Gilfelt写的BadgeView实现的,原理就是继承TextView,初始化的时候拿到目标View的ViewParent,添加FramLayout,再将目标View和该BadgeView添加到此FramLayout中形成角标的效果,角标可设多个方向。
View actionView = MenuItemCompat.getActionView(item)是兼容到3.0下面的获取actionView的方法,这样子就可以取出View进行加角标操作,而badgeView.setBadgeMargin是因为角标方向跟实际有出入,这样子我们可以设Margin调整至想要的位置。
②接下来说下TabLayout的加角标问题,传统的TabLayout用法是这样的:
TabLayout的标题的确定是通过mTabLayout.setupWithViewPager(mViewPager)实现的,
源码:
然后这里调用this.setTabsFromPagerAdapter(adapter);
实际上就是去调用adapter.getPageTitle(i)方法,所以使用此TabLayout就要adapter要实现getPageTitle()方法.
然后我们能拿到TabLayout标题的view吗?
很遗憾,还是没有。
不过,TabLayout有TabLayout.Tab.setCustomView(view)的方法,虽然他的TabLayout.Tab.getCustomView()方法修饰符是default的(谷歌我也是醉了),但是我们可以再外面加载布局拿到引用直接加角标了。
方法如下:
tab_title_layout就是一个TextView
首先拿到对应位置的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
①首先说下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
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories