招生热线
0755-86191118 0755-86191118
我的位置: 首页 > 学习专区 > 安卓技术 > android TAb分页菜单实现总结

android TAb分页菜单实现总结

2012-11-27 11:44:00
来源:
[导读] 首先说明的是,我们做APP开发,Tab分页不管是顶部还是底部,都是必不可少的,网上也有太多太多的实现方式了,我在这里总结一下:第一种方式

首先说明的是,我们做APP开发,Tab分页不管是顶部还是底部,都是必不可少的,网上也有太多太多的实现方式了,我在这里总结一下:

第一种方式: TabHost原始方式:

这里实现的是底部菜单:

布局文件:(我们通过RelativeLayout 可以把TabWidget定位在底部)

android:id="@android:id/tabhost"

android:layout_width="fill_parent"

android:layout_height="fill_parent" >

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:orientation="vertical"

android:padding="3dp" >

<framelayout< p=""> </framelayout<>

android:id="@android:id/tabcontent"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:layout_weight="1" >

 

android:id="@android:id/tabs"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:layout_alignBottom="@android:id/tabcontent"

android:background="@drawable/tabbar_bg" />

在这里我们将说明一下:之前我是获取到TabWidget的view试图及内部icon和title,然后控制实现其效果,但是我们也可以用另外一种方式,也就是我们调用TabHost.TabSpec 的setIndicator(View view);这个方法,我们可以定制显示的view,

代码片段:

/***

* 创建footerview

*/

public void createFooterView() {

tabHost = getTabHost(); // The activity TabHost

view = new TabView(this, R.drawable.tabbar_icon_home,

R.drawable.tabbar_icon_home_selecotr);

view.setBackgroundDrawable(this.getResources().getDrawable(

R.drawable.footer_view_selector));

intent = new Intent(MainActivity.this, HomeActivity.class);

spec = tabHost.newTabSpec("num1").setIndicator(view).setContent(intent);

tabHost.addTab(spec);

view = new TabView(this, R.drawable.tabbar_icon_search,

R.drawable.tabbar_icon_search_selecotr);

view.setBackgroundDrawable(this.getResources().getDrawable(

R.drawable.footer_view_selector));

intent = new Intent(MainActivity.this, HomeActivity.class);

spec = tabHost.newTabSpec("num2").setIndicator(view).setContent(intent);

tabHost.addTab(spec);

view = new TabView(this, R.drawable.tabbar_icon_cart,

R.drawable.tabbar_icon_cart_selector);

view.setBackgroundDrawable(this.getResources().getDrawable(

R.drawable.footer_view_selector));

intent = new Intent(MainActivity.this, HomeActivity.class);

spec = tabHost.newTabSpec("num3").setIndicator(view).setContent(intent);

tabHost.addTab(spec);

view = new TabView(this, R.drawable.tabbar_icon_more,

R.drawable.tabbar_icon_more_selecotr);

view.setBackgroundDrawable(this.getResources().getDrawable(

R.drawable.footer_view_selector));

intent = new Intent(MainActivity.this, HomeActivity.class);

spec = tabHost.newTabSpec("num4").setIndicator(view).setContent(intent);

tabHost.addTab(spec);

}

/***

* 自定义view

*

*/

class TabView extends LinearLayout {

ImageView imageView;

public TabView(Context c, int drawable, int drawableselec) {

super(c);

imageView = new ImageView(c);

// 可以定制点击后状态

StateListDrawable listDrawable = new StateListDrawable();

// 未选

listDrawable.addState(SELECTED_STATE_SET, this.getResources()

.getDrawable(drawableselec));

// 选择

listDrawable.addState(ENABLED_STATE_SET, this.getResources()

.getDrawable(drawable));

imageView.setImageDrawable(listDrawable);// 引用 StateListDrawable

setGravity(Gravity.CENTER);

addView(imageView);

}

}

这样我们就实现想要的效果了.(建议使用这种方法,我的项目就是用的这个实现的.)

如果我是图标和文字分开的,我们也可以用(RadioButton代替,也许大家都不陌生,一会我简单介绍下)

 

 

这个源码是因为项目里面用的。有时间整理下上传上去,不过我相信大家看过都会做出来的.

第二种方法:GridView+ActivityGroup (图片 ,文字)

(为了省事,我把上下tab分页整理到一个demo里面了.)

这个的布局文件我就不显示了,因为比较简单,我们还是来看代码吧.

代码片段:

/***

* 适配器

*

* @author Administrator

*

*/

public class ImageAdapter extends BaseAdapter {

private Context mContext;

private ImageTextButton[] imgItems;

private int selResId;

/***

*

* @param c

* @param picIds

* @param titles

* @param width

* @param height

* @param selResId

*/

public ImageAdapter(Context c, int[] picIds, String titles[], int width,

int height, int selResId) {

mContext = c;

this.selResId = selResId;

imgItems = new ImageTextButton[picIds.length];

for (int i = 0; i < picIds.length; i++) {

imgItems[i] = new ImageTextButton(mContext);

imgItems[i]

.setLayoutParams(new GridView.LayoutParams(width, height));// 设置ImageView宽高

imgItems[i].setPadding(2, 2, 2, 2);

// 显示图片与文本

imgItems[i].setImageResource(picIds[i], titles[i]);

}

}

@Override

public int getCount() {

return imgItems.length;

}

@Override

public Object getItem(int position) {

return position;

}

@Override

public long getItemId(int position) {

return position;

}

/***

* 设置选中后的效果

*/

public void SetFocus(int index) {

for (int i = 0; i < imgItems.length; i++) {

// 先把所有设为最初状态

if (i != index) {

imgItems[i].setBackgroundResource(0);// 回到最初样式

}

}

// 选中设置

imgItems[index].setBackgroundResource(selResId);

}

@Override

public View getView(int position, View convertView, ViewGroup parent) {

ImageTextButton imageView;

if (convertView == null) {

imageView = imgItems[position];

} else {

imageView = (ImageTextButton) convertView;

}

return imageView;

}

}

在这里我们用到了自定义控件,其实就是把imageview 和textview 整到一起了

/***

* 自定义控件(图片文字)

*/

public class ImageTextButton extends LinearLayout {

private ImageView button = null;

private TextView text = null;

private Context context;

public ImageTextButton(Context context) {

this(context, null);

this.context = context;

}

public ImageTextButton(Context context, AttributeSet attrs) {

super(context, attrs);

LayoutInflater.from(context).inflate(R.layout.imagetextbutton, this,

true);

button = (ImageView) this.findViewById(R.id.button);

text = (TextView) this.findViewById(R.id.btnText);

text.setSingleLine(true);

}

public void setImageResource(int image_id, String title) {

Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),

image_id);

button.setBackgroundDrawable(new BitmapDrawable(bitmap));

text.setText(title);

}

public void setImageBitmap(Bitmap bitmap) {

if (button != null)

button.setImageBitmap(bitmap);

}

public void setBackgroundDrawable(Drawable drawable, int Width, int Hdight) {

if (button != null) {

button.setBackgroundDrawable(drawable);

button.setMinimumHeight(Hdight);

button.setMinimumWidth(Width);

}

}

public void setText(String title) {

if (text != null)

text.setText(title);

}

public void setText(int ResID) {

if (text != null)

text.setText(ResID);

}

public void setWidth(int width) {

button.setMaxWidth(width);

}

public void setHeight(int height) {

button.setMaxHeight(height);

}

}

我们只需要在oncreate中调用即可:

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

Navigation_Top_Bar = (GridView) this

.findViewById(R.id.Navigation_Top_Bar);

Navigation_Buttom_Bar = (GridView) this

.findViewById(R.id.Navigation_Buttom_Bar);

// 获取显示宽度

int width = this.getWindowManager().getDefaultDisplay().getWidth()

/ topbar_image_array.length;

topImgAdapter1 = new ImageAdapter(this, topbar_image_array, titles,

width, 100, R.drawable.cover);

Init(Navigation_Top_Bar, topImgAdapter1);

ButtomImgAdapter2 = new ImageAdapter(this, topbar_image_array, titles,

width, 100, R.drawable.cover);

Init(Navigation_Buttom_Bar, ButtomImgAdapter2);

}

这个实现起来有点复杂,不过用习惯了会觉得别有一翻风味的.我之前就一直用这个方法.

在这里我要说明一点:

imgItems[i].setLayoutParams(new GridView.LayoutParams(width, height));// 设置ImageView宽高

其他的都是细节上的问题,我想你们看过都会ok的.

效果图:

 

 

(怎么样,效果还不错吧。就是实现起来有点负责,不过习惯就好.)

第三种方法:ActivityGroup+一些TextView布局.(在这里我们自定实现动态滚动效果)

详情请查看前面一片文章:android 分页Title栏滑块效果--ActionBar(模拟网易 腾讯等动态效果)

分页Tab的实现方法和上面方法类是,都是运用ActivityGroup的性质,而上面是通过GridView生成,而我们这边是我们自定义View控件实现.

这里我主要说一下怎样实现ActionBar:

代码片段:

/***

* 自定义控件

*

* @author zhangjia

*

* 在这里我要说明一点 我们在创建RectF矩形的时候,

*

* 参照物原点是所在"父控件的左上角".

*

*/

public class ActionBar extends LinearLayout implements OnClickListener {

private ImageView tv1;

private ImageView tv2;

private ImageView tv3;

private ImageView tv4;

private Paint paint;// 画笔

private RectF curRectF;// draw当前bar

private RectF tarRectF;// draw被点击bar

private final int space_x = 0;// 相当于pading.

private final int space_y = 0;// 相当于pading

private final double step = 32;// 速度step.

public ActionBar(Context context) {

super(context);

}

/***

* 构造方法

*

* @param context

* @param attrs

*/

public ActionBar(Context context, AttributeSet attrs) {

super(context, attrs);

setWillNotDraw(false);

LayoutInflater.from(context).inflate(R.layout.action_bar, this, true);

paint = new Paint();

paint.setAntiAlias(true);

tv1 = (ImageView) findViewById(R.id.tv1);

tv2 = (ImageView) findViewById(R.id.tv2);

tv3 = (ImageView) findViewById(R.id.tv3);

tv4 = (ImageView) findViewById(R.id.tv4);

tv1.setOnClickListener(this);

tv2.setOnClickListener(this);

tv3.setOnClickListener(this);

tv4.setOnClickListener(this);

curRectF = null;

tarRectF = null;

}

/***

* invalidate():调用这个方法会执行onDraw()方法,但是前提是:自己把invalidate()方法执行结束在进行执行.

*/

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

canvas.drawColor(Color.BLACK);

paint.setColor(Color.RED);

// 如果当前curRectF=null,也就是第一次访问,则默认为draw第一个bar

if (curRectF == null)

curRectF = new RectF(tv1.getLeft() + space_x, tv1.getTop()

+ space_y, tv1.getRight() - space_x, tv1.getBottom()

- space_y);

// 第一次方位tarRectF=null,默认为draw

if (tarRectF == null)

tarRectF = new RectF(tv1.getLeft() + space_x, tv1.getTop()

+ space_y, tv1.getRight() - space_x, tv1.getBottom()

- space_y);

/***

* 作用:如果在这个范围内则,以这个为最终位置,(不明的白的话,你可以把这个注释运行下你就知道why了.)

*/

if (Math.abs(curRectF.left - tarRectF.left) < step) {

curRectF.left = tarRectF.left;

curRectF.right = tarRectF.right;

}

/***

* 说明目标在当前的左侧,需要向左移动(每次矩形移动step,则进行invalidate(),从新进行移动...)

*/

if (curRectF.left > tarRectF.left) {

curRectF.left -= step;

curRectF.right -= step;

invalidate();// 继续刷新,从而实现滑动效果,每次step32.

}

/***

* 说明目标在当前的右侧,需要向右移动(每次矩形移动step,则进行invalidate(),从新进行移动...)

*/

else if (curRectF.left < tarRectF.left) {

curRectF.left += step;

curRectF.right += step;

invalidate();

}

// canvas.drawRect(curRectF, paint);

// 参数,矩形,弧度,画笔

canvas.drawRoundRect(curRectF, 5, 5, paint);

}

/****

* 这里要记录目标矩形的坐标

*/

@Override

public void onClick(View v) {

tarRectF.left = v.getLeft() + space_x;

tarRectF.right = v.getRight() - space_x;

invalidate();// 刷新

System.out.println("tarRectF.top=" + tarRectF.top + ",v.getTop()="

+ v.getTop() + ", v.getBottom()" + v.getBottom());

}

}

上面已经讲的很详细了,就不啰嗦了.

效果图:

 

 

大致就这么多了。

额外:还有一点就是有的会用到RadioButton这个控件,其实就是对其进行了一些调整,这里我简单说明一下应用:

可以取消button样式,用android:drawableTop显示图片,从而达到想要的效果.

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent" >

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:layout_gravity="bottom"

android:background="@drawable/maintab_toolbar_bg"

android:gravity="center"

android:orientation="horizontal" >

android:id="@+id/button1"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_gravity="center"

android:layout_weight="1"

android:background="@drawable/home_btn_bg"

android:button="@null"

android:drawableTop="@drawable/icon_1_n"

android:gravity="center"

android:paddingTop="5dp"

android:text="首页"

android:textSize="12sp" />

android:id="@+id/button2"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_weight="1"

android:background="@drawable/home_btn_bg"

android:button="@null"

android:drawableTop="@drawable/icon_2_n"

android:gravity="center"

android:paddingTop="5dp"

android:text="短信"

android:textSize="12sp" />

android:id="@+id/button3"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_weight="1"

android:background="@drawable/home_btn_bg"

android:button="@null"

android:drawableTop="@drawable/icon_3_n"

android:gravity="center"

android:paddingTop="5dp"

android:text="联系人"

android:textSize="12sp" />

android:id="@+id/button4"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_weight="1"

android:background="@drawable/home_btn_bg"

android:button="@null"

android:drawableTop="@drawable/icon_4_n"

android:gravity="center"

android:paddingTop="5dp"

android:text="搜索"

android:textSize="12sp" />

 

 

这里我们还需要selector.xml

实现点击效果.

 

示例图:

 

 

就说这么多了,情况因人而异.。

【北大青鸟深圳嘉华】

评论