Android自定义的TabBar

来源:互联网 发布:node.js java 编辑:程序博客网 时间:2024/05/16 11:08

http://www.oschina.net/code/snippet_731007_24519

Android自定义的TabBar,自定义了几个属性,可以在xml布局文件中使用,Tab的标题、图标等属性可以在布局文件中完成配置,Java代码中只需要指定Tab跳转的监听接口。可以在所有Android版本使用,建议配合ViewPager使用。

attrs.xml

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="TabBar">        <attr name="icons" format="reference" />        <!-- icons是一个存放drawable资源文件名的数组 -->        <attr name="titles" format="reference" />        <!-- titles是一个存放string的数组 -->        <attr name="IconAboveTitle" format="boolean" />        <!-- 允许指定分隔线的drawable -->        <attr name="Seperator" format="reference" />    </declare-styleable> </resources>

TabBar.java

package com.pupa.common.widget;import com.pupa.common.util.StringHelper;import com.pupa.TabBarDemo.R;import android.annotation.SuppressLint;import android.content.Context;import android.content.res.Resources;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Rect;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.view.Display;import android.view.Gravity;import android.view.View;import android.view.WindowManager;import android.widget.ImageView;import android.widget.ImageView.ScaleType;import android.widget.LinearLayout;import android.widget.TextView;public class TabBar extends LinearLayout {private static final String TAG = "TabBar";private final TabBar mTabBar; // 自己private final Context mContext;private final AttributeSet mAttrs;private int mDefStyle;private Paint mPaint;private int mCurrentTabMaskColor;private int mCurrentTabMaskAlpha;private String mResPackageName;private CharSequence[] mTitles;private CharSequence[] mIconNames;private Drawable[] mIcons;private Drawable mSeperator;private int mSeperatorResId;private int mSeperatorWidth;private boolean mIconAboveTitle;private int mCurrentTabIndex;private int mTabCount;private int mTabWidth;private int mPosition;private OnCurrentTabChangedListener mTabChangedListener;public static final int POSITION_TOP = 1; // 位于顶部或者底部public static final int POSITION_BOTTOM = 2;public TabBar(Context context) {this(context, null);// TODO Auto-generated constructor stub}public TabBar(Context context, AttributeSet attrs) {super(context, attrs);setWillNotDraw(false); // 重要!!!mContext = context;mAttrs = attrs;mCurrentTabIndex = -1;mTabCount = 0;mSeperatorWidth = 0;mPosition = POSITION_TOP;mCurrentTabMaskColor = Color.BLACK;mCurrentTabMaskAlpha = 0x5f;mPaint = new Paint();mTabBar = this;init();// TODO Auto-generated constructor stub}@SuppressWarnings("deprecation")public void init() {getResourcesFromXml();this.setOrientation(LinearLayout.HORIZONTAL);this.setPadding(0, 0, 0, 0);WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);Display dp = wm.getDefaultDisplay();mTabWidth = dp.getWidth();mTabCount = mTitles.length;if (mTabCount > 0) {if (mSeperator != null) {Bitmap bmp = BitmapFactory.decodeResource(getResources(),mSeperatorResId);mSeperatorWidth = bmp.getWidth();mTabWidth = mTabWidth - (mTabCount - 1) * mSeperatorWidth;bmp.recycle();bmp = null;}mTabWidth = mTabWidth / mTabCount; // 计算每个tab的宽度mCurrentTabIndex = 0;}LayoutParams inParams = new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT);LayoutParams outParams = new LayoutParams(mTabWidth,LayoutParams.WRAP_CONTENT);LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);View.OnClickListener clkListener = new View.OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubint index = (Integer) v.getTag();if (index != mCurrentTabIndex) {if (mTabChangedListener != null)mTabChangedListener.onCurrentTabChanged(index);mCurrentTabIndex = index;mTabBar.invalidate();}}};//逐个添加Tabfor (int i = 0; i < mTabCount; ++i) {LinearLayout tab = new LinearLayout(mContext);tab.setOrientation(LinearLayout.VERTICAL);tab.setPadding(0, 0, 0, 0);tab.setTag(i); // 设置内部标号tab.setClickable(true);ImageView imv = new ImageView(mContext);imv.setScaleType(ScaleType.CENTER);if (i < mIcons.length)imv.setImageDrawable(mIcons[i]);TextView tv = new TextView(mContext);tv.setGravity(Gravity.CENTER_HORIZONTAL);tv.setText(mTitles[i]);if (mIconAboveTitle) { // 图标在标题之上tab.addView(imv, inParams);tab.addView(tv, inParams);} else { // 标题在图标之上tab.addView(tv, inParams);tab.addView(imv, inParams);}tab.setOnClickListener(clkListener);this.addView(tab, outParams);if (mSeperator != null && i < mTabCount - 1) {ImageView sep = new ImageView(mContext);sep.setImageDrawable(mSeperator);this.addView(sep, params);}}}/** * 设置当前Tab的序号 *  * @param index *            你想指定的Tab的序号 */public void setCurrentTab(int index) {if (index > -1 && index < mTabCount&&index!=mCurrentTabIndex) {mCurrentTabIndex = index;this.invalidate();if (mTabChangedListener != null)mTabChangedListener.onCurrentTabChanged(mCurrentTabIndex);}}public void setOnCurrentTabChangedListener(OnCurrentTabChangedListener listener) {mTabChangedListener = listener;}/** * 设置TabBar在顶端还是底端.真实位置由你的Activity的布局文件决定,这里仅仅是作一个标识, 根据这个信息可以增加一些自定义的效果 *  * @param i *            顶端TabBar.POSITION_TOP或底端TabBar.POSITION_BOTTOM */public void setTabBarPosition(int i) {mPosition = i;}/** * 设定工程中R.java文件的包名,因为在解析出各个Tab的icon时要用到。如果是默认值则无需指定 *  * @param name *            R.java文件的包名 */public void setResourcesPackageName(String name) {mResPackageName = name;}/** * 设置Tab选中后的颜色,默认alpha为0x5f *  * @param c *            rgb颜色值 */public void setCurrentTabMaskColor(int rgb) {mCurrentTabMaskColor = rgb;}/** * 设置Tab选中后的颜色.为什么要重载这个方法呢?因为我总是记不住Alpha值0和255谁是全透明, 于是宁愿把ARGB颜色中A跟RGB分开设置。。 *  * @param rgb *            rgb颜色值 * @param a *            alpha值 */public void setCurrentTabMaskColor(int rgb, int a) {mCurrentTabMaskColor = rgb;mCurrentTabMaskAlpha = a;}/** * 获取Tab个数 *  * @return Tab个数 */public int getTabCount() {return mTabCount;}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);int h = this.getHeight();if (mCurrentTabIndex > -1 && mCurrentTabIndex < mTabCount) {int startX = (mTabWidth + mSeperatorWidth) * mCurrentTabIndex;mPaint.setColor(mCurrentTabMaskColor);mPaint.setAlpha(mCurrentTabMaskAlpha);mPaint.setStyle(Paint.Style.FILL);canvas.drawRect(new Rect(startX, 0, startX + mTabWidth, h), mPaint);}}/** * 从布局文件的属性值中解析出各个资源 */private void getResourcesFromXml() {TypedArray ta = mContext.obtainStyledAttributes(mAttrs,R.styleable.TabBar, 0, 0);mIconNames = ta.getTextArray(R.styleable.TabBar_icons);mTitles = ta.getTextArray(R.styleable.TabBar_titles);mIconAboveTitle = ta.getBoolean(R.styleable.TabBar_IconAboveTitle, true);mSeperator = ta.getDrawable(R.styleable.TabBar_Seperator);mSeperatorResId = ta.getResourceId(R.styleable.TabBar_Seperator, -1);if (!StringHelper.notNullAndNotEmpty(mResPackageName))mResPackageName = mContext.getPackageName();if (mTitles == null) {mTitles = new CharSequence[0]; // 避免为null}if (mIconNames == null) {mIconNames = new CharSequence[0]; // 避免为null}Resources res = mContext.getResources();mIcons = new Drawable[mIconNames.length];for (int i = 0; i < mIconNames.length; ++i) {int id = res.getIdentifier(mIconNames[i].toString(), "drawable",mResPackageName);if (id != 0)mIcons[i] = res.getDrawable(id);}ta.recycle();}public interface OnCurrentTabChangedListener {public void onCurrentTabChanged(int index);}}

arrays.xml

<?xml version="1.0" encoding="utf-8"?><resources>    <string-array name="tab_titles">        <item>Tab1</item>        <item>Tab2</item>    </string-array>    <string-array name="tab_icons">        <item>tab1_icon</item>        <item>tab2_icon</item>    </string-array></resources>

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    xmlns:pupa="http://schemas.android.com/apk/res/com.pupa.TabDemo"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context=".MainActivity" >    <com.pupa.common.widget.TabBar        android:id="@+id/MainTabBar"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_alignParentTop="true"        android:background="@android:drawable/title_bar"        pupa:Seperator="@drawable/tab_seperator"        pupa:icons="@array/tab_icons"        pupa:titles="@array/tab_titles" >    </com.pupa.common.widget.TabBar>    <android.support.v4.view.ViewPager        android:id="@+id/MainViewPager"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_below="@id/MainTabBar" /></RelativeLayout>

TabBarDemo.zip ~ 703KB     下载


原创粉丝点击