Android TAb分页菜单实现总结
来源:互联网 发布:c语言如何生成exe文件 编辑:程序博客网 时间:2024/06/05 05:26
Android TAb分页菜单实现总结
首先说明的是,我们做APP开发,Tab分页不管是顶部还是底部,都是必不可少的,网上也有太多太多的实现方式了,我在这里总结一下:
第一种方式: TabHost原始方式:(链接另一篇文章 http://www.linuxidc.com/Linux/2012-08/69303.htm )
这里实现的是底部菜单:
布局文件:(我们通过RelativeLayout 可以把TabWidget定位在底部)
- <?xml version="1.0" encoding="utf-8"?>
- <TabHost xmlns:Android="http://schemas.android.com/apk/res/android"
- android:id="@android:id/tabhost"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- android:padding="3dp" >
- <FrameLayout
- android:id="@android:id/tabcontent"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:layout_weight="1" >
- </FrameLayout>
- <TabWidget
- 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" />
- </RelativeLayout>
- </TabHost>
在这里我们将说明一下:之前我是获取到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(模拟网易 腾讯等动态效果)http://www.linuxidc.com/Linux/2012-08/69305.htm
分页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显示图片,从而达到想要的效果.
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
- <RadioGroup
- 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" >
- <RadioButton
- 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" />
- <RadioButton
- 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" />
- <RadioButton
- 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" />
- <RadioButton
- 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" />
- </RadioGroup>
- </RelativeLayout>
这里我们还需要selector.xml
实现点击效果.
- <?xml version="1.0" encoding="utf-8"?>
- <selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:drawable="@drawable/home_btn_bg_s" android:state_enabled="true" android:state_focused="true" android:state_pressed="false"/>
- <item android:drawable="@drawable/home_btn_bg_s" android:state_enabled="true" android:state_pressed="true"/>
- <item android:drawable="@drawable/home_btn_bg_d" android:state_checked="true" android:state_enabled="true"/>
- </selector>
示例图:
就说这么多了,情况因人而异.
本篇文章相关代码下载
免费下载地址在 http://linux.linuxidc.com/
用户名与密码都是www.linuxidc.com
具体下载目录在 /2012年资料/8月/30日/Android TAb分页菜单实现总结
- android TAb分页菜单实现总结
- Android TAb分页菜单实现总结
- Android实现底部菜单Tab
- 【Android】FragmentTabHost实现底部Tab菜单选项
- Android ActivityGroup + GridView 实现Tab分页标签 .
- android 之用ActivityGroup 实现Tab分页
- Android 动态Tab分页效果实现
- Android Tab 分页标签的实现方式
- Android Tab页实现总结
- Tab菜单的实现
- Tab形式的菜单实现总结TabHost 和 FragmentTabHost
- Android Tab分页
- Android实现Tab切换效果总结
- Android Tab实现总结之Viewpager
- 通过Fragment + Viewpager+Gridview实现Android Tab切换菜单
- Android之ActivityGroup + GridView 实现Tab分页标签
- Android 基于GridView和ActivityGroup实现的TAB分页
- Android之ActivityGroup + GridView 实现Tab分页标签
- Python分段下载文件
- NGINX中的线程池加速
- [Rtsp]RTSP对实时摄像头视频流进行转换(FFmpeg+FFserver)
- 使用Nginx+FFMPEG搭建HLS直播转码服务器
- CUDA编程接口:共享存储器实现矩阵相乘
- Android TAb分页菜单实现总结
- Android RxJava使用介绍(四) RxJava的操作符
- 让FFMPEG支持实时流“伴随”转码
- 字符串匹配之BF算法
- composer更新不成功,启用国内镜像网站的配置更改办法
- 学习笔记-基础知识7-多线程
- IKEV2 VPN
- Dictionary<T,T>的基本用法
- fseek获取大于4G的文件大小的问题