关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » 安卓开发 »Android UI 之 Tab类型界面总结

    Android UI 之 Tab类型界面总结

    2015-08-12 00:00:00 出处:CSDN
    分享

    Android 程序中实现Tab类型界面很常见,本人在做项目的时候也经常用到,所以想在这里总结一下,实现tab类型界面的几种方式,供大家参考。如有不对之处,欢迎大家指正!

    一、TabActivity + TabWidget + TabHost.

    实现TAB类型界面,首先想到的就是这种方式。但是在API level 13之后官方就不建议使用它了。不过还是在这里简单说一下它的使用吧。

    使用它的关键就是布局文件了。需要在布局中添加<TabHost>、<TabWidget>、<FrameLayout>这三个控件,id分别是系统提供的:@android:id/tabhost 、@android:id/tabs 、@android:id/tabcontent 。

    < xml version="1.0" encoding="utf-8" >
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    
        <TabHost
            android:id="@android:id/tabhost"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >
    
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical" >
    
                <!-- 可以指定tabwidget的位置    android:layout_alignParentBottom="true" -->
    
                <TabWidget
                    android:id="@android:id/tabs"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_alignParentBottom="false" >
                </TabWidget>
    
                <FrameLayout
                    android:id="@android:id/tabcontent"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_below="@android:id/tabs" >
    
                    <LinearLayout
                        android:id="@+id/tab1"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:background="#DEB887"
                        android:orientation="vertical" >
                    </LinearLayout>
    
                    <LinearLayout
                        android:id="@+id/tab2"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:background="#BCEE68"
                        android:orientation="vertical" >
                    </LinearLayout>
    
                    <LinearLayout
                        android:id="@+id/tab3"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:background="#7D9EC0"
                        android:orientation="vertical" >
                    </LinearLayout>
                </FrameLayout>
            </RelativeLayout>
        </TabHost>
    
    </LinearLayout>

    一个linearlayout对应一个tab页面的布局。

    tabHost = getTabHost();
    
    		tabHost.addTab(tabHost
    				.newTabSpec("111")
    				.setIndicator("", getResources().getDrawable(R.drawable.wuyong))
    				.setContent(R.id.tab1));
    
    		tabHost.addTab(tabHost
    				.newTabSpec("222")
    				.setIndicator("",
    						getResources().getDrawable(R.drawable.gongsunsheng))
    				.setContent(R.id.tab2));
    
    		tabHost.addTab(tabHost.newTabSpec("333")
    				.setIndicator("", getResources().getDrawable(R.drawable.likui))
    				.setContent(R.id.tab3));
    
    		tabHost.setBackgroundColor(Color.argb(150, 22, 70, 150));
    		tabHost.setCurrentTab(0);
    		tabHost.setOnTabChangedListener(new OnTabChangeListener() {
    			@Override
    			public void onTabChanged(String tabId) {
    				Toast.makeText(FourthActivity.this, tabId, Toast.LENGTH_SHORT)
    						.show();
    			}
    		});

    二、ViewPager + PageAdapter

    目前最常见的tab界面就是使用viewpager来实现了。

    先来说一下viewpager的一般使用步骤:

    1. 在布局文件中添加viewpager控件

    2. 在代码中设置viewpager适配器,该类继承与pagerAdapter或它的子类。必须实现以下四个方法:

    (1)getCount()

    (2)instantiateItem()

    (3)destroyItem()

    (4)isViewFromObject()

    3. 初始化viewpager控件,设置监听器

    4. 设置监听事件(setOnPageChangeListener)

    下面看一下这种方式的效果图:

    主要的功能代码如下:

    private void init() {
    		viewPager = (ViewPager) findViewById(R.id.first_vp);
    		LayoutInflater inflater = LayoutInflater.from(this);
    		View view1 = inflater.inflate(R.layout.first_layout1, null);
    		View view2 = inflater.inflate(R.layout.first_layout2, null);
    		View view3 = inflater.inflate(R.layout.first_layout3, null);
    		list.add(view1);
    		list.add(view2);
    		list.add(view3);
    
    		viewPager.setAdapter(pagerAdapter);
    		viewPager.setOnPageChangeListener(new OnPageChangeListener() {
    			@Override
    			public void onPageSelected(int arg0) {
    				setDots(arg0);
    			}
    
    			@Override
    			public void onPageScrolled(int arg0, float arg1, int arg2) {
    			}
    
    			@Override
    			public void onPageScrollStateChanged(int arg0) {
    			}
    		});
    	}
    private PagerAdapter pagerAdapter = new PagerAdapter() {  
    //官方建议这么写  
            @Override  
            public boolean isViewFromObject(View arg0, Object arg1) {  
                return arg0 == arg1;  
            }  
     //返回一共有多少个界面  
            @Override  
            public int getCount() {  
                return list.size();  
            }  
    //实例化一个item  
            @Override  
            public Object instantiateItem(ViewGroup container, int position) {  
                container.addView(list.get(position));  
                return list.get(position);  
            }  
    //销毁一个item  
            @Override  
            public void destroyItem(ViewGroup container, int position, Object object) {  
                container.removeView(list.get(position));  
            }  
    
        };

    适配器中必须要实现以上的四个方法。

    假如只有这几个页面,交互性肯定是不好的,所以需要添加“指示器”,用来标识当前的页面是哪一个!我在这里用点来实现。就像效果图显示的那样。

    /**
    	 * 初始化底部的点
    	 */
    	private void initDots() {
    		pointLayout = (LinearLayout) findViewById(R.id.point_layout);
    		dots = new ImageView[list.size()];
    		for (int i = 0; i < list.size(); i++) {
    			dots[i] = (ImageView) pointLayout.getChildAt(i);
    		}
    		currentIndex = 0;
    		dots[currentIndex].setBackgroundResource(R.drawable.dian_down);
    	}
    
    	/**
    	 * 当滚动的时候更换点的背景图
    	 */
    	private void setDots(int position) {
    		if (position < 0 || position > list.size() - 1
    				|| currentIndex == position) {
    			return;
    		}
    		dots[position].setBackgroundResource(R.drawable.dian_down);
    		dots[currentIndex].setBackgroundResource(R.drawable.dian);
    		currentIndex = position;
    	}

    重点就是页面切换之后,点也要切换。这时候就用到了OnPageChangeListener中的onPageSelected(int arg0)这个方法了。

    @Override
    			public void onPageSelected(int arg0) {
    				setDots(arg0);
    			}

    三、Fragment + FragmentManager

    fragment相信大家在项目中肯定都用过。这个方法主要就是利用fragmentManager对fragment的事务管理功能。

    // 三个选项卡
    	private LinearLayout tab1Layout, tab2Layout, tab3Layout;
    	// 默认选中第一个tab
    	private int index = 1;
    	// fragment管理类
    	private FragmentManager fragmentManager;
    	// 三个fragment
    	private Fragment tab1Fragment, tab2Fragment, tab3Fragment;
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_second);
    		fragmentManager = getSupportFragmentManager();
    		init();
    	}
    
    	/**
    	 * 初始化控件
    	 */
    	private void init() {
    		tab1Layout = (LinearLayout) findViewById(R.id.tab1_layout);
    		tab2Layout = (LinearLayout) findViewById(R.id.tab2_layout);
    		tab3Layout = (LinearLayout) findViewById(R.id.tab3_layout);
    
    		tab1Layout.setOnClickListener(this);
    		tab2Layout.setOnClickListener(this);
    		tab3Layout.setOnClickListener(this);
    		//
    		setDefaultFragment();
    	}
    
    	/**
    	 * 设置默认显示的fragment
    	 */
    	private void setDefaultFragment() {
    		FragmentTransaction transaction = fragmentManager.beginTransaction();
    		tab1Fragment = new Tab1Fragment();
    		transaction.replace(R.id.content_layout, tab1Fragment);
    		transaction.commit();
    	}
    
    	/**
    	 *切换fragment
    	 * @param newFragment
    	 */
    	private void replaceFragment(Fragment newFragment) {
    		FragmentTransaction transaction = fragmentManager.beginTransaction();
    		if (!newFragment.isAdded()) {
    			transaction.replace(R.id.content_layout, newFragment);
    			transaction.commit();
    		} else {
    			transaction.show(newFragment);
    		}
    	}
    
    	/**
    	 * 改变现象卡的选中状态
    	 */
    	private void clearStatus() {
    		if (index == 1) {
    			tab1Layout.setBackgroundColor(getResources().getColor(R.color.tab));
    		} else if (index == 2) {
    			tab2Layout.setBackgroundColor(getResources().getColor(R.color.tab));
    		} else if (index == 3) {
    			tab3Layout.setBackgroundColor(getResources().getColor(R.color.tab));
    		}
    	}
    
    	@Override
    	public void onClick(View v) {
    		clearStatus();
    		switch (v.getId()) {
    		case R.id.tab1_layout:
    			if (tab1Fragment == null) {
    				tab1Fragment = new Tab1Fragment();
    			}
    			replaceFragment(tab1Fragment);
    			tab1Layout.setBackgroundColor(getResources().getColor(
    					R.color.tab_down));
    			index = 1;
    			break;
    		case R.id.tab2_layout:
    			if (tab2Fragment == null) {
    				tab2Fragment = new Tab2Fragment();
    			}
    			replaceFragment(tab2Fragment);
    			tab2Layout.setBackgroundColor(getResources().getColor(
    					R.color.tab_down));
    			index = 2;
    			break;
    		case R.id.tab3_layout:
    			if (tab3Fragment == null) {
    				tab3Fragment = new Tab3Fragment();
    			}
    			replaceFragment(tab3Fragment);
    			tab3Layout.setBackgroundColor(getResources().getColor(
    					R.color.tab_down));
    			index = 3;
    			break;
    		}
    	}

    每一个fragment对应一个布局,点击不同的按钮来切换页面。效果如下图:

    四、ViewPager + Fragment + FragmentPagerAdapter

    假如想使用fragment的时候又想可以左右滑动,就可以使用这种方式。主要的部分就在viewpager的适配器。它的适配器继承FragmentPagerAdapter.

    package com.tab.view.demo3;
    
    import java.util.ArrayList;
    
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentManager;
    import android.support.v4.app.FragmentPagerAdapter;
    public class FragmentAdapter extends FragmentPagerAdapter {
    	private ArrayList<Fragment> list;
    	public FragmentAdapter(FragmentManager fm, ArrayList<Fragment> list) {
    		super(fm);
    		this.list = list;
    	}
    	@Override
    	public Fragment getItem(int arg0) {
    		return list.get(arg0);
    	}
    	@Override
    	public int getCount() {
    		return list.size();
    	}
    }

    需要传入FragmentManager对象和一个存放fragment的list对象。

    /**
    	 * 初始化viewpager
    	 */
    	private void initViewPager() {
    		viewPager = (ViewPager) findViewById(R.id.third_vp);
    		fragmentsList = new ArrayList<>();
    		Fragment fragment = new Tab1Fragment();
    		fragmentsList.add(fragment);
    		fragment = new Tab2Fragment();
    		fragmentsList.add(fragment);
    		fragment = new Tab3Fragment();
    		fragmentsList.add(fragment);
    
    		viewPager.setAdapter(new FragmentAdapter(getSupportFragmentManager(),
    				fragmentsList));
    		viewPager.setCurrentItem(0);
    		viewPager.setOnPageChangeListener(this);
    	}

    对button添加点击事件。

    @Override
    	public void onClick(View v) {
    		switch (v.getId()) {
    		case R.id.tab1_tv:
    			viewPager.setCurrentItem(0);
    			break;
    		case R.id.tab2_tv:
    			viewPager.setCurrentItem(1);
    			break;
    		case R.id.tab3_tv:
    			viewPager.setCurrentItem(2);
    			break;
    		}
    	}

    我在布局文件中添加了一个imageview作为指示器。假如想第一种tab类型界面的实现方式那样在onPageSelected()方法中进行设置,效果是只能当页面完全切换过来之后才能把指示器移动过去。要想实现滑动页面的时候同时移动指示器,就需要在onPageScrolled()方法中进行设置。

    @Override
    	public void onPageScrolled(int position, float positionOffset,
    			int positionOffsetPixels) {
    		offset = (screen1_3 - cursorImg.getLayoutParams().width) / 2;
    		Log.d("111", position + "--" + positionOffset + "--"
    				+ positionOffsetPixels);
    		final float scale = getResources().getDisplayMetrics().density;
    		if (position == 0) {// 0<->1
    			lp.leftMargin = (int) (positionOffsetPixels / 3) + offset;
    		} else if (position == 1) {// 1<->2
    			lp.leftMargin = (int) (positionOffsetPixels / 3) + screen1_3 +offset;
    		}
    		cursorImg.setLayoutParams(lp);
    		currentIndex = position;
    	}

    onPageScrolled中的三个参数比较重要。第一个参数是position。它的含义是表示当前显示的界面中的第一个界面。意思就是的当滑动的时候,有可能出现两个界面,position指的是左边的界面。第二个参数是positionOffset指的是偏移量的比例,取值范围是[0, 1)。第三个参数是positionOffsetPixels是指偏移的像素值。后两个参数都相对页面(一个page)来说的。

    我之前有看到过设置指示器的时候用的前两个参数的,我也试了一下,OK的。不过感觉比较复杂,看了一下官方api,用第三个参数更简单。关键就是理解第一个参数position。用这种方法我只在代码里有两个判断就可以完成了。

    效果图如下:

    五、Viewpager + PagerTitleStrip / PagerTabStrip

    这种方式没有上一种效果好看,而且标题变动。看一下效果图:

    布局文件:

    < xml version="1.0" encoding="utf-8" >
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    
        <android.support.v4.view.ViewPager
            android:id="@+id/fifth_vp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center" >
    
            <android.support.v4.view.PagerTabStrip
                android:id="@+id/fifth_strip"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="top"
                android:background="#7EC0EE"
                android:padding="10dip" />
        </android.support.v4.view.ViewPager>
    
    </LinearLayout>

    先来说一下PagerTitleStrip和PagerTabStrip的区别:PagerTitleStrip没有指示器,只有标题,且标题没有响应事件;而PagerTabStrip是带有指示器的,当然也有标题,具有相应事件。二者的实现只在布局文件中有区别,只需要把android.support.v4.view.PagerTabStrip改成android.support.v4.viewPagerTitleStrip即可。

    代码中需要注意的就是,在适配器中重写getPageTitle(int)方法来显示标题。

    PagerAdapter pagerAdapter = new PagerAdapter() {          
                    //此处省略其他的方法 
    // 重写此方法即可显示标题  
    @Override  
    public CharSequence getPageTitle(int position) {  
        return titleList.get(position);  
    }
    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    正版 Windows 11产品密钥怎么查找/查看?

    还有3个月,微软将停止 Windows 10 的更新

    Windows 10 终止支持后,企业为何要立即升级?

    Windows 10 将于 2025年10 月终止技术支持,建议迁移到 Windows 11

    Windows 12 发布推迟,微软正全力筹备Windows 11 25H2更新

    Linux 退出 mail的命令是什么

    Linux 提醒 No space left on device,但我的空间看起来还有不少空余呢

    hiberfil.sys文件可以删除吗?了解该文件并手把手教你删除C盘的hiberfil.sys文件

    Window 10和 Windows 11哪个好?答案是:看你自己的需求

    盗版软件成公司里的“隐形炸弹”?老板们的“法务噩梦” 有救了!

    IT头条

    公安部:我国在售汽车搭载的“智驾”系统都不具备“自动驾驶”功能

    02:03

    液冷服务器概念股走强,博汇、润泽等液冷概念股票大涨

    01:17

    亚太地区的 AI 驱动型医疗保健:2025 年及以后的下一步是什么?

    16:30

    智能手机市场风云:iPhone领跑销量榜,华为缺席引争议

    15:43

    大数据算法和“老师傅”经验叠加 智慧化收储粮食尽显“科技范”

    15:17

    技术热点

    SQL汉字转换为拼音的函数

    windows 7系统无法运行Photoshop CS3的解决方法

    巧用MySQL加密函数对Web网站敏感数据进行保护

    MySQL基础知识简介

    Windows7和WinXP下如何实现不输密码自动登录系统的设置方法介绍

    windows 7系统ip地址冲突怎么办?windows 7系统IP地址冲突问题的

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。