两种实现选项卡功能----自定义和TabLayout

Posted 大前端圈

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了两种实现选项卡功能----自定义和TabLayout相关的知识,希望对你有一定的参考价值。

选项卡在应用中使用的特别多,也特别常见,以前实现选项卡功能,使用第三方库来实现,一般TabPageIndicator+viewPager,有时觉得比较笨重,没有必要

现在自己写个功能来实现下,实现效果如下图,滑动时,红色指示线也跟着滑动:


1,此功能主要是imageView的位移动画+ViewPager来实现,布局代码如下:activity_define.xml

<LinearLayout 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"
              android:background="#F8F8F8"
              android:orientation="vertical" >
    <LinearLayout
        android:id="@+id/llyout_my_coupon_sort"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
        <View
            android:layout_width="0.3dp"
            android:layout_height="match_parent"
            android:layout_marginBottom="5dp"
            android:layout_marginTop="5dp"
            android:background="#d7d7d7" />
        <TextView
            android:id="@+id/tv_not_spending"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/shape_my_coupon_tab"
            android:gravity="center"
            android:onClick="notSpending"
            android:text="未消费"
            android:textColor="#898787" />
        <View
            android:layout_width="0.3dp"
            android:layout_height="match_parent"
            android:layout_marginBottom="5dp"
            android:layout_marginTop="5dp"
            android:background="#d7d7d7" />
        <TextView
            android:id="@+id/tv_yet_spent"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/shape_my_coupon_tab"
            android:gravity="center"
            android:onClick="yetSpwnt"
            android:text="已消费"
            android:textColor="#898787" />
    </LinearLayout>

    <ImageView
        android:id="@+id/img_tabLine"
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:contentDescription="@null"
        android:scaleType="matrix" />
    <View
        android:layout_width="match_parent"
        android:layout_height="0.3dp"
        android:layout_marginBottom="5dp"
        android:background="#d7d7d7" />
    <android.support.v4.view.ViewPager
        android:id="@+id/vp_coupon"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

2,两个Fragment,比较简单:

/**
 * 未消費券Fragment类
 */
@SuppressLint("InflateParams")
public class MyCouponNotSpendingFragment extends Fragment
	@Override
	public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) 
		TextView tv = new TextView(getActivity());
		tv.setTextSize(24.f);
		tv.setPadding(15,10,15,10);
		tv.setText("未消费");
		return tv;
	

/**
 * 已消費券Fragment类
 */
@SuppressLint("InflateParams")
public class MyCouponYetSpentFragment extends Fragment

	@Override
	public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) 
		TextView tv = new TextView(getActivity());
		tv.setTextSize(24.f);
		tv.setPadding(15,10,15,10);
		tv.setText("已消费");
		return tv;
	
3,写ViewPager的适配器:

/**
 * 我的券Fragment 页面适配器
 */
public class MyCouponFragmentAdapter extends FragmentPagerAdapter 
	public MyCouponFragmentAdapter(FragmentManager fm) 
		super(fm);
	
	@Override
	public Fragment getItem(int position) 
		Fragment fragment = null;
		switch (position) 
		// 我的券未消费
		case 0:
			fragment = new MyCouponNotSpendingFragment();
			break;
		// 我的券已消费
		case 1:
			fragment = new MyCouponYetSpentFragment();
			break;
		
		return fragment;
	
	@Override
	public int getCount() 
		return 2;
	
	@Override
	public void destroyItem(ViewGroup container, int position, Object object) 
		// super.destroyItem(container, position, object);
	

4,主程序界面代码 ,DefineActivity.java:

/**
 * 自定义tab导航
 */
public class DefineActivity extends FragmentActivity implements View.OnClickListener 

    private ViewPager mViewPager;
    // ViewPager适配器
    private MyCouponFragmentAdapter adapter = null;
    private int tabWidth;
    private DisplayMetrics dm = new DisplayMetrics();
    private ImageView img_tabLine;
    // 已消费
    private TextView tv_yet_spent;
    // 未消费
    private TextView tv_not_spending;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_define);
        // 初始化控件
        initView();
        //初始化数据
        initData();
        // 绑定券页面
        bindPageData();
        // 注册监听
        registerListener();
    

    /**
     * 初始化控件
     */
    private void initView() 
        mViewPager = (ViewPager) findViewById(R.id.vp_coupon);
        img_tabLine = (ImageView) findViewById(R.id.img_tabLine);
        tv_not_spending = (TextView) findViewById(R.id.tv_not_spending);
        tv_yet_spent = (TextView) findViewById(R.id.tv_yet_spent);
        tv_not_spending.setTextColor(getResources().getColor(R.color.textcolor_mine_red));
    
    /**
     * 初始化数据
     */
    private void initData() 
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        tabWidth = dm.widthPixels / 2;
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.tab_line);
        // /Bitmap b = Bitmap.createBitmap(bitmap, 0, 0, tabWidth, 8);
        // 设置tab的宽度和高度
        Bitmap bitmap2 = Bitmap.createScaledBitmap(bitmap, tabWidth, 8, true);
        img_tabLine.setImageBitmap(bitmap2);
    
    /**
     * 绑定我的券页面及数据
     */
    private void bindPageData() 
        adapter = new MyCouponFragmentAdapter(getSupportFragmentManager());
        mViewPager.setAdapter(adapter);
    
    /**
     * 注册事件监听
     */
    private void registerListener() 
        tv_not_spending.setOnClickListener(this);
        tv_yet_spent.setOnClickListener(this);
        mViewPager.setOnPageChangeListener(new PageListener());
    

    @Override
    public void onClick(View v) 
        switch (v.getId()) 
            // 未消费
            case R.id.tv_not_spending: 
                resetTab();
                tv_not_spending.setTextColor(getResources().getColor(R.color.textcolor_mine_red));
                mViewPager.setCurrentItem(0);
            
            break;
            // 已消费
            case R.id.tv_yet_spent: 
                resetTab();
                tv_yet_spent.setTextColor(getResources().getColor(R.color.textcolor_mine_red));
                mViewPager.setCurrentItem(1);
            
            break;
            default:
                break;
        

    
    /**
     * viewPager滑动监听
     */
    public class PageListener implements ViewPager.OnPageChangeListener 
        @Override
        public void onPageScrollStateChanged(int arg0) 

        
        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) 
            // new一个矩阵
            Matrix matrix = new Matrix();
            // 设置激活条的最终位置
            switch (arg0) 
                case 0:
                    // 使用set直接设置到那个位置
                    matrix.setTranslate(0, 0);
                    break;
                case 1:
                    matrix.setTranslate(tabWidth, 0);
                    break;
            
            // 在滑动的过程中,计算出激活条应该要滑动的距离
            float t = (tabWidth) * arg1;
            // 使用post追加数值
            matrix.postTranslate(t, 0);
            img_tabLine.setImageMatrix(matrix);
        

        @Override
        public void onPageSelected(int position) 
            switch (position) 
                case 0: 
                    resetTab();
                    tv_not_spending.setTextColor(getResources().getColor(R.color.textcolor_mine_red));
                    mViewPager.setCurrentItem(0);
                
                break;
                case 1: 
                    resetTab();
                    tv_yet_spent.setTextColor(getResources().getColor(R.color.textcolor_mine_red));
                    mViewPager.setCurrentItem(1);
                
                break;
                default:
                    break;
            
        
    
    /**
     * 文字全部重置为默认状态
     */
    private void resetTab() 
        tv_not_spending.setTextColor(getResources().getColor(R.color.details));
        tv_yet_spent.setTextColor(getResources().getColor(R.color.details));
    
至此,基本功能已经完成,是不是觉得代码比较多。

现在google发布了新的Android Support Design,里面包含了几个新的控件,其中就有一个TabLayout,它就可以完成TabPageIndicator的效果,而且还是官方的,最好的是它可以兼容到2.2以上版本,包括2.2。使用的 android studio进行开发的,所以引用TabLayout很简单,只要在build.gradle中加入compile 'com.android.support:design:22.2.0'即可。

下面使用TabLayout来实现以上功能,效果图如下:


1,界面布局TabLayout+ViewPager,如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              android:orientation="vertical">

    <android.support.design.widget.TabLayout
        android:id="@+id/tab_FindFragment_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#4876FF"
        app:tabIndicatorColor="#FFFFFF"
        app:tabSelectedTextColor="#999999"
        app:tabTextColor="#FFFFFF"
        app:tabTextAppearance = "@style/tabLayoutTextSize"
        />
    <!--app:tabIndicatorColor="@color/white"                 // 下方滚动的下划线颜色
        app:tabSelectedTextColor="@color/gray"               // tab被选中后,文字的颜色
        app:tabTextColor="@color/white"                      // tab默认的文字颜色
     -->
    <android.support.v4.view.ViewPager
        android:id="@+id/vp_FindFragment_pager"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        />

</LinearLayout>
2,主程序代码如下:

/**
 * TabLayout导航
 */
public class TabActivity  extends Activity 
    private TabLayout mTabLayout;
    private ViewPager mViewPager;

    private List<String> mTitle = new ArrayList<String>();
    private List<String> mDatas = new ArrayList<String>();

    private MyPagerAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_tab);

        mTabLayout = (TabLayout) findViewById(R.id.tab_FindFragment_title);
        mViewPager = (ViewPager) findViewById(R.id.vp_FindFragment_pager);

        initDatas();
        mAdapter = new MyPagerAdapter();

        //1,设置Tab的标题来自PagerAdapter.getPageTitle()
        mTabLayout.setTabsFromPagerAdapter(mAdapter);
        //2,设置TabLayout的选项卡监听
        /*mTabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() 
            @Override
            public void onTabSelected(TabLayout.Tab tab) 
                mViewPager.setCurrentItem(tab.getPosition());
            
            @Override
            public void onTabUnselected(TabLayout.Tab tab) 

            
            @Override
            public void onTabReselected(TabLayout.Tab tab) 

            
        );*/
        //3,设置TabLayout.TabLayoutOnPageChangeListener监听给ViewPager
        /*TabLayout.TabLayoutOnPageChangeListener listener =
                new TabLayout.TabLayoutOnPageChangeListener(mTabLayout);
        mViewPager.addOnPageChangeListener(listener);*/

        //4,viewpager设置适配器
        mViewPager.setAdapter(mAdapter);
        //这个方法是addOnPageChangeListener和setOnTabSelectedListener的封装。代替2,3步骤
        mTabLayout.setupWithViewPager(mViewPager);

    

    class MyPagerAdapter extends PagerAdapter 
        @Override
        public CharSequence getPageTitle(int position) 
            return mTitle.get(position);
        
        @Override
        public int getCount() 
            return mDatas.size();
        
        @Override
        public boolean isViewFromObject(View view, Object object) 
            return view == object;
        
        @Override
        public Object instantiateItem(View container, int position) 
            TextView tv = new TextView(TabActivity.this);
            tv.setTextSize(24.f);
            tv.setPadding(15,10,15,10);
            tv.setText(mDatas.get(position));
            ((ViewPager) container).addView(tv);
            return tv;
        
        @Override
        public void destroyItem(ViewGroup container, int position, Object object) 
            ((ViewPager) container).removeView((View) object);
        
    

    public void initDatas()
        mTitle.add("热门推荐");
        mTitle.add("热门收藏");
        mTitle.add("本月热榜");
        mTitle.add("今日热榜");

        mDatas.add("热门推荐");
        mDatas.add("热门收藏");
        mDatas.add("本月热榜");
        mDatas.add("今日热榜");
    
如果 文字的字体修改,文字的大小怎么设置呢,只需要给TabLayout设置样式就可以了

比如:

app:tabTextAppearance = "@style/tabLayoutTextSize"
在style.xml中添加:

    <style name="tabLayoutTextSize" 
parent="TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse">
        <item name="android:textSize">16dp</item>
        <item name="android:textAllCaps">false</item>
    </style>

这样是不是很简单。

至此,基本功能已实现,如有疑问欢迎留言或加群讨论:196615382,如需源码,点击下载。。。


以上是关于两种实现选项卡功能----自定义和TabLayout的主要内容,如果未能解决你的问题,请参考以下文章

使用react-grid-layout和react-full-screen实现一个可自定义和全屏展示的dashboard页面

使用react-grid-layout和react-full-screen实现一个可自定义和全屏展示的dashboard页面

java注解的自定义和使用

java注解的自定义和使用

为啥 Azure 将不同的 HTML 嵌入到自定义和内置策略的自定义 UI 注册表单中?

CodeIngiter 路由控制路由自定义和 基于SEO的url重写等