官方安卓tab栏高度底部tab栏可以换icon颜色吗

安卓Material Design新规范:底部Tab导航加入【android吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:1,188,665贴子:
安卓Material Design新规范:底部Tab导航加入收藏
主流安卓机的屏幕尺寸达到5.0以上之后,Google倡导的Material Design设计语言开始发生微妙的变化。Google官方刚刚更新了面向开发者的 Material Design设计指南 。新版本中加入了名为「Bottom Navigation」组件,也就是我们在iOS应用中经常见到的底部Tab导航条。在此之前,Google +和Google Photos两款官方应用在版本更新中先后引入了这一设计,并被资深的Android爱好者和产品经理大为吐槽。
但沉思片刻就会发现,随着手机屏幕尺寸的逐渐增加,大部分用户已经很难单手触摸到5吋以上手机的对角线位置。这意味着,无论是左利手还是右利手,Material Design此前倡导的隐藏式导航或者顶部导航带来不便的几率会大大增加。相比之下,底部Tab导航则可以免去这些麻烦,单手即可覆盖,用户也不必呼出某些定制ROM中的单手模式然后再进行操作。
至于Android向来引以为豪的左右滑动Holo特性,Google并未顺势应用于底部导航中。此前滑动切换频道或界面的顺畅感一去不复返了,点按操作成为用户最常用的交互动作,这与iOS9中的交互设计趋于一致。
对比Android和iOS两大移动操作系统的发展历史,从互相借鉴功能细节,到最近几年来的设计语言升级,有着明显的趋同倾向。iOS和Android之间的藩篱对普通用户而言不再不可逾越,这终归是件好事。——————TECH2IPO / 创见
心疼火腿肠
我们中出了一个叛徒———From SONY Xperia(TM) Z5 Dual White
又是你如果结局是你,久一点真的没关系……
然而国产厂商并不管这些,安卓心,苹果型
13级了   --谁叫我复合肥,谁没丁丁(ノ=Д=)ノ┻━┻
那我为何不中出
火腿肠又多了层下巴
那不是老大的smartbar么
反正我只想祝福Luke早日归西
好利害的样子   --来自没事总喜欢来个几炮的客户端
其实底栏还是很好用滴,但是为啥左右滑动的去掉了←_←
想当年老大的smartbar被喷粗翔,结果现在
---贴吧极速版 For UWP
还是底部好,点着方便。还有受不了虚拟键设计,大爱棒子实体键
国产UI玩过的东西了
登录百度帐号推荐应用Android开源项目——带图标文字的底部导航栏IconTabPageIndicator-爱编程
Android开源项目——带图标文字的底部导航栏IconTabPageIndicator
接下来的博客计划是,在《Android官方技术文档翻译》之间会发一些Android开源项目的介绍,直接剩下的几篇Android技术文档发完,然后就是Android开源项目和Gradle翻译了。当然,其他的文章笔记也会偶尔发一下。
本文原创,转载请注明在CSDN上的出处:
http://blog.csdn.net/maosidiaoxian/article/details/
本篇文章介绍的是一个底部导航栏,叫IconTabPageIndicator,一个带图标文字的导航栏。
实际上,这个项目才三个类,而且也只完成了这一种导航栏。该项目参考了JakeWharton大神两年前的项目ViewPagerIndicator的实现,基于其中的一种导航做了修改,而实现这种图标文字的导航栏,且可以设定图标或文字的大小,不用担心过大的图标把文字顶出去或把图标给撑肥。
为什么我会知道得这么清楚呢?因为这个就是我写的,哈哈。
Eclipse用户就自己去下载项目,然后把资源和代码拷进项目吧。
版权所有 爱编程 (C) Copyright 2012. . All Rights Reserved.
闽ICP备号-3
微信扫一扫关注爱编程,每天为您推送一篇经典技术文章。73059人阅读
【Android 精彩案例】(37)
【Android 自定义控件实战】(28)
转载请标明出处:,本文出自:1、概述学习Android少不了模仿各种app的界面,自从微信6.0问世以后,就觉得微信切换时那个变色的Tab图标屌屌的,今天我就带大家自定义控件,带你变色变得飞起~~好了,下面先看下效果图:清晰度不太好,大家凑合看~~有木有觉得这个颜色弱爆了了的,,,下面我动动手指给你换个颜色:有没有这个颜色比较妖一点~~~好了~下面开始介绍原理。2、原理介绍通过上面的效果图,大家可能也猜到了,我们的图标并非是两张图片,而是一张图,并且目标颜色是可定制的,谁让现在动不动就谈个性化呢。那么我们如何做到,可以让图标随心所遇的变色了,其实原理,在我的博客中出现了很多次了,下面你将看到一张熟悉的图:有没有很熟悉的感脚,我们实际上还是利用了Paint的Xfermode,这次我们使用的是:Mode.DST_INDst_IN回顾一下什么效果,先绘制Dst,设置Mode,再绘制Src,则显示的是先后绘图的交集区域,且是Dst.再仔细观察下我们的图标:为了方便大家的观看,我特意拿ps选择了一下我们图标的非透明区域,可以看到,我们这个小机器人非透明区域就是被线框起来的部分。然后,我们图标变色的原理就出现了:1、先绘制一个颜色(例如:粉红)2、设置Mode=DST_IN3、绘制我们这个可爱的小机器人回答我,显示什么,是不是显示交集,交集是什么?交集是我们的小机器人的非透明区域,也就是那张脸,除了两个眼;好了,那怎么变色呢?我绘制一个颜色的时候,难道不能设置alpha么~~~到此,大家应该已经了解了我们图标的绘制的原理了吧。如果你对Mode不熟悉:建议移步至:3、自定义图标控件我们的整个界面不用说,是ViewPager+Fragment ,现在关注的是底部~~接下来我们考虑,底部的Tab,Tab我们的布局是LinearLayout,内部四个View,通过设置weight达到均分~~这个View就是我们的自定义的图标控件了,我们叫做:ChangeColorIconWithTextView接下来考虑,应该有什么属性公布出来1、自定义属性想了一下,我决定把图标,图标颜色,图标下显示的文字,文字大小这四个属性作为自定义属性。那就自定义属性走起了:a、values/attr.xml&?xml version=&1.0& encoding=&utf-8&?&
&resources&
&attr name=&icon& format=&reference& /&
&attr name=&color& format=&color& /&
&attr name=&text& format=&string& /&
&attr name=&text_size& format=&dimension& /&
&declare-styleable name=&ChangeColorIconView&&
&attr name=&icon& /&
&attr name=&color& /&
&attr name=&text& /&
&attr name=&text_size& /&
&/declare-styleable&
&/resources&b、在布局文件中使用 &com.zhy.weixin6.ui.ChangeColorIconWithTextView
android:id=&@+id/id_indicator_one&
android:layout_width=&0dp&
android:layout_height=&fill_parent&
android:layout_weight=&1&
android:padding=&5dp&
zhy:icon=&@drawable/ic_menu_start_conversation&
zhy:text=&@string/tab_weixin&
zhy:text_size=&12sp& /&自己注意命名空间的写法,xmlns:zhy=&/apk/res/应用的包名&。c、在构造方法中获取public class ChangeColorIconWithTextView extends View
private Bitmap mB
private Canvas mC
private Paint mP
private int mColor = 0xFF45C01A;
* 透明度 0.0-1.0
private float mAlpha = 0f;
private Bitmap mIconB
* 限制绘制icon的范围
private Rect mIconR
* icon底部文本
private String mText = &微信&;
private int mTextSize = (int) TypedValue.applyDimension(
PLEX_UNIT_SP, 10, getResources().getDisplayMetrics());
private Paint mTextP
private Rect mTextBound = new Rect();
public ChangeColorIconWithTextView(Context context)
super(context);
* 初始化自定义属性值
* @param context
* @param attrs
public ChangeColorIconWithTextView(Context context, AttributeSet attrs)
super(context, attrs);
// 获取设置的图标
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.ChangeColorIconView);
int n = a.getIndexCount();
for (int i = 0; i & i++)
int attr = a.getIndex(i);
switch (attr)
case R.styleable.ChangeColorIconView_icon:
BitmapDrawable drawable = (BitmapDrawable) a.getDrawable(attr);
mIconBitmap = drawable.getBitmap();
case R.styleable.ChangeColorIconView_color:
mColor = a.getColor(attr, 0x45C01A);
case R.styleable.ChangeColorIconView_text:
mText = a.getString(attr);
case R.styleable.ChangeColorIconView_text_size:
mTextSize = (int) a.getDimension(attr, TypedValue
.PLEX_UNIT_SP, 10,
getResources().getDisplayMetrics()));
a.recycle();
mTextPaint = new Paint();
mTextPaint.setTextSize(mTextSize);
mTextPaint.setColor(0xff555555);
// 得到text绘制范围
mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBound);
}可以看到,我们在构造方法中获取了自定义的属性,并且计算了文本占据的控件存在我们的mTextBound中。2、图标的绘制区域的选择我们考虑下,有了属性,我们需要绘制一个文本,文本之上一个图标,我们怎么去控制绘制的区域呢?我们的View显示区域,无非以下三种情况:针对这三种情况,我门的图标的边长应该是什么呢?我觉得边长应该是:控件的高度-文本的高度-内边距 & 与 &控件的宽度-内边距 &两者的小值;大家仔细推敲一下;好了,有了上面的边长的结论,我们就开始计算图标的绘制范围了: @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 得到绘制icon的宽
int bitmapWidth = Math.min(getMeasuredWidth() - getPaddingLeft()
- getPaddingRight(), getMeasuredHeight() - getPaddingTop()
- getPaddingBottom() - mTextBound.height());
int left = getMeasuredWidth() / 2 - bitmapWidth / 2;
int top = (getMeasuredHeight() - mTextBound.height()) / 2 - bitmapWidth
// 设置icon的绘制范围
mIconRect = new Rect(left, top, left + bitmapWidth, top + bitmapWidth);
3、绘制图标绘制图标有很多步骤呀,我来列一列1、计算alpha(默认为0)2、绘制原图3、在绘图区域,绘制一个纯色块(设置了alpha),此步绘制在内存的bitmap上4、设置mode,针对内存中的bitmap上的paint5、绘制我们的图标,此步绘制在内存的bitmap上6、绘制原文本7、绘制设置alpha和颜色后的文本8、将内存中的bitmap绘制出来根据上面的步骤,可以看出来,我们的图标其实绘制了两次,为什么要绘制原图呢,因为我觉得比较好看。3-5步骤,就是我们上面分析的原理6-7步,是绘制文本,可以看到,我们的文本就是通过设置alpha实现的@Override
protected void onDraw(Canvas canvas)
int alpha = (int) Math.ceil((255 * mAlpha));
canvas.drawBitmap(mIconBitmap, null, mIconRect, null);
setupTargetBitmap(alpha);
drawSourceText(canvas, alpha);
drawTargetText(canvas, alpha);
canvas.drawBitmap(mBitmap, 0, 0, null);
private void setupTargetBitmap(int alpha)
mBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(),
Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mPaint = new Paint();
mPaint.setColor(mColor);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setAlpha(alpha);
mCanvas.drawRect(mIconRect, mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaint.setAlpha(255);
mCanvas.drawBitmap(mIconBitmap, null, mIconRect, mPaint);
private void drawSourceText(Canvas canvas, int alpha)
mTextPaint.setTextSize(mTextSize);
mTextPaint.setColor(0xff333333);
mTextPaint.setAlpha(255 - alpha);
canvas.drawText(mText, mIconRect.left + mIconRect.width() / 2
- mTextBound.width() / 2,
mIconRect.bottom + mTextBound.height(), mTextPaint);
private void drawTargetText(Canvas canvas, int alpha)
mTextPaint.setColor(mColor);
mTextPaint.setAlpha(alpha);
canvas.drawText(mText, mIconRect.left + mIconRect.width() / 2
- mTextBound.width() / 2,
mIconRect.bottom + mTextBound.height(), mTextPaint);
}关于绘制文本区域的计算,首先是起点x:mIconRect.left + mIconRect.width() / 2- mTextBound.width() / 2 有点长哈,文本mIconRect.left + mIconRect.width() / 2这个位置,在图标水平区域的中心点,这个应该没有疑问;图标水平区域的中点- mTextBound.width() / 2 开始绘制文本,是不是就是居中在图标的下面;有人可能会问:你怎么知道文本宽度小于图标,我有5个字咋办?5个字怎么了,照样是居中显示,不信你试试~~4、公布设置透明度的方法到此,我们的图标控件写完了,但是还没有把我们的控制icon的方法放出去: public void setIconAlpha(float alpha)
this.mAlpha =
invalidateView();
private void invalidateView()
if (Looper.getMainLooper() == Looper.myLooper())
invalidate();
postInvalidate();
}我们叫做setIconAlpha,避免了和setAlpha冲突,设置完成后,invalidate一下~~~到此就真的结束了,接下来看用法。4、实战1、布局文件&LinearLayout xmlns:android=&/apk/res/android&
xmlns:zhy=&/apk/res/com.zhy.weixin6.ui&
xmlns:tools=&/tools&
android:layout_width=&match_parent&
android:layout_height=&match_parent&
android:orientation=&vertical& &
&android.support.v4.view.ViewPager
android:id=&@+id/id_viewpager&
android:layout_width=&fill_parent&
android:layout_height=&0dp&
android:layout_weight=&1& &
&/android.support.v4.view.ViewPager&
&LinearLayout
android:layout_width=&fill_parent&
android:layout_height=&60dp&
android:background=&@drawable/tabbg&
android:orientation=&horizontal& &
&com.zhy.weixin6.ui.ChangeColorIconWithTextView
android:id=&@+id/id_indicator_one&
android:layout_width=&0dp&
android:layout_height=&fill_parent&
android:layout_weight=&1&
android:padding=&5dp&
zhy:icon=&@drawable/ic_menu_start_conversation&
zhy:text=&@string/tab_weixin&
zhy:text_size=&12sp& /&
&com.zhy.weixin6.ui.ChangeColorIconWithTextView
android:id=&@+id/id_indicator_two&
android:layout_width=&0dp&
android:layout_height=&fill_parent&
android:layout_weight=&1&
android:padding=&5dp&
zhy:icon=&@drawable/ic_menu_friendslist&
zhy:text=&@string/tab_contact&
zhy:text_size=&12sp& /&
&com.zhy.weixin6.ui.ChangeColorIconWithTextView
android:id=&@+id/id_indicator_three&
android:layout_width=&0dp&
android:layout_height=&fill_parent&
android:layout_weight=&1&
android:padding=&5dp&
zhy:icon=&@drawable/ic_menu_emoticons&
zhy:text=&@string/tab_find&
zhy:text_size=&12sp& /&
&com.zhy.weixin6.ui.ChangeColorIconWithTextView
android:id=&@+id/id_indicator_four&
android:layout_width=&0dp&
android:layout_height=&fill_parent&
android:layout_weight=&1&
android:padding=&5dp&
zhy:icon=&@drawable/ic_menu_allfriends&
zhy:text=&@string/tab_me&
zhy:text_size=&12sp& /&
&/LinearLayout&
&/LinearLayout&2、MainActivitypackage com.zhy.weixin6.
import java.lang.reflect.F
import java.lang.reflect.M
import java.util.ArrayL
import java.util.L
import android.annotation.SuppressL
import android.os.B
import android.support.v4.app.F
import android.support.v4.app.FragmentA
import android.support.v4.app.FragmentPagerA
import android.support.v4.view.ViewP
import android.support.v4.view.ViewPager.OnPageChangeL
import android.view.M
import android.view.V
import android.view.View.OnClickL
import android.view.ViewC
import android.view.W
@SuppressLint(&NewApi&)
public class MainActivity extends FragmentActivity implements
OnPageChangeListener, OnClickListener
private ViewPager mViewP
private List&Fragment& mTabs = new ArrayList&Fragment&();
private FragmentPagerAdapter mA
private String[] mTitles = new String[] { &First Fragment!&,
&Second Fragment!&, &Third Fragment!&, &Fourth Fragment!& };
private List&ChangeColorIconWithTextView& mTabIndicator = new ArrayList&ChangeColorIconWithTextView&();
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setOverflowShowingAlways();
getActionBar().setDisplayShowHomeEnabled(false);
mViewPager = (ViewPager) findViewById(R.id.id_viewpager);
initDatas();
mViewPager.setAdapter(mAdapter);
mViewPager.setOnPageChangeListener(this);
private void initDatas()
for (String title : mTitles)
TabFragment tabFragment = new TabFragment();
Bundle args = new Bundle();
args.putString(&title&, title);
tabFragment.setArguments(args);
mTabs.add(tabFragment);
mAdapter = new FragmentPagerAdapter(getSupportFragmentManager())
public int getCount()
return mTabs.size();
public Fragment getItem(int arg0)
return mTabs.get(arg0);
initTabIndicator();
public boolean onCreateOptionsMenu(Menu menu)
getMenuInflater().inflate(R.menu.main, menu);
private void initTabIndicator()
ChangeColorIconWithTextView one = (ChangeColorIconWithTextView) findViewById(R.id.id_indicator_one);
ChangeColorIconWithTextView two = (ChangeColorIconWithTextView) findViewById(R.id.id_indicator_two);
ChangeColorIconWithTextView three = (ChangeColorIconWithTextView) findViewById(R.id.id_indicator_three);
ChangeColorIconWithTextView four = (ChangeColorIconWithTextView) findViewById(R.id.id_indicator_four);
mTabIndicator.add(one);
mTabIndicator.add(two);
mTabIndicator.add(three);
mTabIndicator.add(four);
one.setOnClickListener(this);
two.setOnClickListener(this);
three.setOnClickListener(this);
four.setOnClickListener(this);
one.setIconAlpha(1.0f);
public void onPageSelected(int arg0)
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels)
// Log.e(&TAG&, &position = & + position + & , positionOffset = &
// + positionOffset);
if (positionOffset & 0)
ChangeColorIconWithTextView left = mTabIndicator.get(position);
ChangeColorIconWithTextView right = mTabIndicator.get(position + 1);
left.setIconAlpha(1 - positionOffset);
right.setIconAlpha(positionOffset);
public void onPageScrollStateChanged(int state)
public void onClick(View v)
resetOtherTabs();
switch (v.getId())
case R.id.id_indicator_one:
mTabIndicator.get(0).setIconAlpha(1.0f);
mViewPager.setCurrentItem(0, false);
case R.id.id_indicator_two:
mTabIndicator.get(1).setIconAlpha(1.0f);
mViewPager.setCurrentItem(1, false);
case R.id.id_indicator_three:
mTabIndicator.get(2).setIconAlpha(1.0f);
mViewPager.setCurrentItem(2, false);
case R.id.id_indicator_four:
mTabIndicator.get(3).setIconAlpha(1.0f);
mViewPager.setCurrentItem(3, false);
* 重置其他的Tab
private void resetOtherTabs()
for (int i = 0; i & mTabIndicator.size(); i++)
mTabIndicator.get(i).setIconAlpha(0);
public boolean onMenuOpened(int featureId, Menu menu)
if (featureId == Window.FEATURE_ACTION_BAR && menu != null)
if (menu.getClass().getSimpleName().equals(&MenuBuilder&))
Method m = menu.getClass().getDeclaredMethod(
&setOptionalIconsVisible&, Boolean.TYPE);
m.setAccessible(true);
m.invoke(menu, true);
} catch (Exception e)
return super.onMenuOpened(featureId, menu);
private void setOverflowShowingAlways()
// true if a permanent menu key is present, false otherwise.
ViewConfiguration config = ViewConfiguration.get(this);
Field menuKeyField = ViewConfiguration.class
.getDeclaredField(&sHasPermanentMenuKey&);
menuKeyField.setAccessible(true);
menuKeyField.setBoolean(config, false);
} catch (Exception e)
e.printStackTrace();
Activity里面代码虽然没什么注释,但是很简单哈,就是初始化Fragment,得到我们的适配器,然后设置给ViewPager;initTabIndicator我们初始化我们的自定义控件,以及加上了点击事件;唯一一个需要指出的就是:我们在onPageScrolled中,动态的获取position以及positionOffset,然后拿到左右两个View,设置positionOffset ;这里表示下惭愧,曾经在&的onPageScrolled中写了一堆的if else,在上线后,也有同学立马就提出了,一行代码搞定~~所以,我们这里简单找了下规律,已经没有if else的身影了~~~还剩两个反射的方法,是控制Actionbar的图标的,和点击menu按键,将ActionBar的menu显示在正常区域的~~3、TabFragmentpackage com.zhy.weixin6.
import android.graphics.C
import android.os.B
import android.support.v4.app.F
import android.view.G
import android.view.LayoutI
import android.view.V
import android.view.ViewG
import android.widget.TextV
public class TabFragment extends Fragment
private String mTitle = &Default&;
public TabFragment()
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
if (getArguments() != null)
mTitle = getArguments().getString(&title&);
TextView textView = new TextView(getActivity());
textView.setTextSize(20);
textView.setBackgroundColor(Color.parseColor(&#ffffffff&));
textView.setGravity(Gravity.CENTER);
textView.setText(mTitle);
return textV
好了,到此我们的整个案例就结束了~~大家可以在布局文件中设置各种颜色,4个不同颜色也可以,尽情的玩耍吧~~我建了一个QQ群,方便大家交流。群号:----------------------------------------------------------------------------------------------------------博主部分视频已经上线,如果你不喜欢枯燥的文本,请猛戳(初录,期待您的支持):
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
积分:48557
积分:48557
排名:第59名
原创:201篇
评论:14573条
长期为您推荐优秀博文、开源项目、视频等,进入还有好玩的等着你,欢迎扫一扫。
请勿重复加群,Thx
文章:11篇
阅读:203652
文章:10篇
阅读:117890
文章:67篇
阅读:5845538

我要回帖

更多关于 ionic2 tabicon 的文章

 

随机推荐