Google在2015的IO大会上,给我们带来了更加详细的Material Design设计规范,同时,也给我们带来了全新的Android Design Support Library,在这个support库里面,Google给我们提供了更加规范的MD设计风格的控件。最重要的是,Android Design Support Library的兼容性更广,直接可以向下兼容到Android 2.2。

这两天需要做一个仿京东详情的页面,上面的Tab切换,以前都是自己写Viewpager+fragment,或者Indicator的深度定制,一直想尝试一下TabLayout,于是就有了下面的坑。

然后下面是我简单的实现效果(个人觉得很坑,还不如自己自定义的导航器)

添加引用库

  1. dependencies {
  2. compile fileTree(dir: 'libs', include: ['*.jar'])
  3. compile 'com.android.support:appcompat-v7:24.2.0'
  4. compile 'com.android.support:design:24.2.0'
  5. compile 'com.android.support:recyclerview-v7:24.2.0'
  6. compile 'com.android.support:cardview-v7:24.2.0'
  7. }

Toolbar与TabLayout

我们来看一下实现的布局:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     xmlns:app="http://schemas.android.com/apk/res-auto"
  4.     android:layout_width="match_parent"
  5.     android:layout_height="match_parent"
  6.     android:orientation="vertical">
  7.     <LinearLayout
  8.         android:layout_width="match_parent"
  9.         android:layout_height="wrap_content"
  10.         android:background="@color/c12"
  11.         android:gravity="center_vertical"
  12.         android:minHeight="45dp"
  13.         android:orientation="horizontal"
  14.         android:paddingLeft="15dp"
  15.         android:paddingRight="15dp">
  16.         <ImageView
  17.             android:id="@+id/back"
  18.             android:layout_width="wrap_content"
  19.             android:layout_height="wrap_content"
  20.             android:background="@drawable/back_icon" />
  21.         <LinearLayout
  22.             android:layout_width="0dp"
  23.             android:layout_height="match_parent"
  24.             android:layout_weight="1"
  25.             android:orientation="horizontal">
  26.             <android.support.design.widget.TabLayout
  27.                 android:id="@+id/tabLayout"
  28.                 android:layout_width="match_parent"
  29.                 android:layout_height="match_parent"
  30.                 app:tabTextAppearance="@style/TabLayoutTextStyle"
  31.                 app:tabGravity="center"
  32.                 app:tabMode="fixed"
  33.                 app:tabTextColor="@color/c7"
  34.                 app:tabSelectedTextColor="@color/c8"/>
  35.         </LinearLayout>
  36.         <ImageView
  37.             android:id="@+id/toolbar_more"
  38.             android:layout_width="wrap_content"
  39.             android:layout_height="wrap_content"
  40.             android:layout_marginLeft="10dp"
  41.             android:background="@drawable/more_icon" />
  42.     </LinearLayout>
  43.     <View style="@style/horizontal_line" />
  44.     <android.support.v4.view.ViewPager
  45.         android:id="@+id/viewPager"
  46.         android:layout_width="match_parent"
  47.         android:layout_height="0dp"
  48.         android:layout_weight="1" />
  49.     <View style="@style/horizontal_line" />
  50.     <LinearLayout
  51.         android:layout_width="match_parent"
  52.         android:layout_height="48dp"
  53.         android:background="@color/c12"
  54.         android:orientation="horizontal">
  55.         <LinearLayout
  56.             android:layout_width="0dp"
  57.             android:layout_height="match_parent"
  58.             android:layout_weight="1">
  59.             <TextView
  60.                 android:layout_width="0dp"
  61.                 android:layout_height="match_parent"
  62.                 android:layout_weight="1"
  63.                 android:gravity="center"
  64.                 android:text="收藏"
  65.                 android:textSize="10sp" />
  66.             <View style="@style/vertical_line" />
  67.             <TextView
  68.                 android:layout_width="0dp"
  69.                 android:layout_height="match_parent"
  70.                 android:layout_weight="1"
  71.                 android:gravity="center"
  72.                 android:text="购物车"
  73.                 android:textSize="10sp" />
  74.         </LinearLayout>
  75.         <LinearLayout
  76.             android:layout_width="0dp"
  77.             android:layout_height="match_parent"
  78.             android:layout_weight="1.5"
  79.             android:background="@color/c8"
  80.             android:gravity="center">
  81.             <TextView
  82.                 style="@style/style_c12_s16"
  83.                 android:gravity="center"
  84.                 android:text="加入购物车" />
  85.         </LinearLayout>
  86.     </LinearLayout>
  87. </LinearLayout>

这布局文件最关键的一点就是android.support.design.widget.TabLayout 标签中的app:tabMode=”scrollable”,他设置tab的模式为“可滑动的”。

其他的用法和Indicator的用法差不多,都需要设置适配器,然后通过数据实现页面的适配。直接上代码
Adapter
  1. public class ProductDetailPagerAdapter extends FragmentPagerAdapter {
  2.  
  3. private List<Fragment> mFragments=null;
  4. private List<String> mTitles=null;
  5.  
  6. public ProductDetailPagerAdapter(FragmentManager fm, List<Fragment> mFragments,List<String> mTitles) {
  7. super(fm);
  8. this.mFragments =mFragments;
  9. this.mTitles=mTitles;
  10. }
  11.  
  12. public ProductDetailPagerAdapter(FragmentManager fm, Fragment... fragments) {
  13. super(fm);
  14. this.mFragments = Arrays.asList(fragments);
  15. }
  16.  
  17. @Override
  18. public Fragment getItem(int position) {
  19. return mFragments.get(position);
  20. }
  21.  
  22. @Override
  23. public int getCount() {
  24. return mFragments.size();
  25. }
  26.  
  27. @Override
  28. public CharSequence getPageTitle(int position) {
  29. return mTitles.get(position);
  30. }
  31. }

主页面的相关逻辑,这里的Fragment就是简单的Fragment。
  1. public class ProductDetailsActivity extends BaseActivity {
  2.     @BindView(R.id.viewPager)
  3.     ViewPager viewPager;
  4.     @BindView(R.id.toolbar_more)
  5.     ImageView toolbarMore;
  6.     @BindView(R.id.tabLayout)
  7.     TabLayout tabLayout;
  8.     private List<Fragment> mFragments;
  9.     private String[] titles = new String[]{"商品", "详情"};
  10.     private ProductDetailPagerAdapter productPagerAdapter = null;
  11.     private MorePopupWindow popupWindow = null;
  12.     @Override
  13.     protected void onCreate(Bundle savedInstanceState) {
  14.         super.onCreate(savedInstanceState);
  15.         setContentView(R.layout.activity_product_details);
  16.         ButterKnife.bind(this);
  17.         init();
  18.     }
  19.     private void init() {
  20.         initViewPager();
  21.     }
  22.     private void initViewPager() {
  23.         mFragments = new ArrayList<>();
  24.         mFragments.add(new ProductFragment());
  25.         mFragments.add(new ProductDetailFragment());
  26.         productPagerAdapter = new ProductDetailPagerAdapter(getSupportFragmentManager(), mFragments, Arrays.asList(titles));
  27.         viewPager.setOffscreenPageLimit(2);
  28.         viewPager.setAdapter(productPagerAdapter);
  29.         viewPager.setCurrentItem(1);
  30.         tabLayout.setupWithViewPager(viewPager);
  31.     }
  32.     @OnClick(R.id.back)
  33.     public void backClick() {
  34.         finish();
  35.     }
  36.     @OnClick(R.id.toolbar_more)
  37.     public void moreClick() {
  38.     }
  39.     private AdapterView.OnItemClickListener onItemClickListener = new AdapterView.OnItemClickListener() {
  40.         @Override
  41.         public void onItemClick(AdapterView<?> parent, View view, int position,
  42.                                 long id) {
  43.             popupWindow.dismiss();
  44.         }
  45.     };
  46.     public static void open(Context context) {
  47.         Intent intent = new Intent(context, ProductDetailsActivity.class);
  48.         context.startActivity(intent);
  49.     }
  50. }

上面的代码都比较简单不做过多的解释,在使用TabLayout的时候需要注意一点:

tabmode有两个属性值:
MODE_FIXED:Fixed tabs display all tabs concurrently and are best used with content that benefits from quick pivots between tabs.
MODE_SCROLLABLE:Scrollable tabs display a subset of tabs at any given moment, and can contain longer tab labels and a larger number of tabs.
MODE_SCROLLABLE适合很多tabs的情况,是可以滚动的,如果你要实现京东的那种挤在一起的效果就需要MODE_FIXED了。
为了更好的满足开发需要,TabLayout实现了自定义TabLayout的样式,然后通过引入
  1. app:tabTextAppearance=""

自定义icon添加到tab

当前的TabLayout没有方法让我们去添加icon,我们可以使用SpannableString结合ImageSpan来实现

  1. private int[] imageResId = {
  2. R.drawable.ic_one,
  3. R.drawable.ic_two,
  4. R.drawable.ic_three
  5. };
  6.  
  7. // ...
  8.  
  9. @Override
  10. public CharSequence getPageTitle(int position) {
  11. // Generate title based on item position
  12. // return tabTitles[position];
  13. Drawable image = context.getResources().getDrawable(imageResId[position]);
  14. image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
  15. SpannableString sb = new SpannableString(" ");
  16. ImageSpan imageSpan = new ImageSpan(image, ImageSpan.ALIGN_BOTTOM);
  17. sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
  18. return sb;
  19. }

运行,发现没有显示,这是因为TabLayout创建的tab默认设置textAllCaps属性为true,这阻止了ImageSpan被渲染出来,可以通过下面的样式文件定义来改变:

  1. <style name="MyCustomTabLayout" parent="Widget.Design.TabLayout">
  2. <item name="tabTextAppearance">@style/MyCustomTextAppearance</item>
  3. </style>
  4.  
  5. <style name="MyCustomTextAppearance" parent="TextAppearance.Design.Tab">
  6. <item name="textAllCaps">false</item>
  7. </style>

然后在getPageTitle方法中设置上有标题的tab

  1. @Override
  2. public CharSequence getPageTitle(int position) {
  3. // Generate title based on item position
  4. Drawable image = context.getResources().getDrawable(imageResId[position]);
  5. image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
  6. // Replace blank spaces with image icon
  7. SpannableString sb = new SpannableString(" " + tabTitles[position]);
  8. ImageSpan imageSpan = new ImageSpan(image, ImageSpan.ALIGN_BOTTOM);
  9. sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
  10. return sb;
  11. }

TabLayout还支持自定义View,通过getTabView来设置,这里就不讲怎么实现了,有兴趣的可以自行研究。



部分代码:https://github.com/xiangzhihong/jingdongApp

android TabLayout实现京东详情效果的更多相关文章

  1. 【京东详情页】——原生js爬坑之放大镜

    一.引言 在商城的详情页中,放大镜的功能是很常见的.这里京东详情页就要做一个仿放大镜的效果,预览如下: 二.实现原理 实际上,放大镜的实现是单纯用几个div,鼠标移入其中一个小图div,触发事件显示另 ...

  2. 【京东详情页】——原生js爬坑之二级菜单

    一.引言 做京东详情页仿写的时候,要用原生js实现顶部菜单的二级菜单显示与隐藏事件的触发. 过程中遇到了一个坑,在这里与大家分享.要实现的效果如下: 二.坑 谁触发事件?显示.隐藏二级菜单       ...

  3. android银行卡匹配、详情展开动画、仿爱奇艺视频拖拽、扫码识别手机号等源码

    Android精选源码 android实现银行卡匹配信息源码 android实现可以展开查看详情的卡片 下拉刷新,上拉加载,侧滑显示菜单等效果RefreshSwipeRecyclerview andr ...

  4. Android 滑动定位+吸附悬停效果实现

    在前两篇文章中,分别介绍了tablayout+scrollview 和 tablayout+recyclerview 实现的滑动定位的功能,文章链接: Android 实现锚点定位 Android t ...

  5. Android RecyclerView 实现支付宝首页效果

    Android RecyclerView 实现支付宝首页效果 [TOC] 虽然我本人不喜欢支付宝的,但是这个网格本身其实还是不错的,项目更新中更改了一个布局为网格模式,类似支付宝.(估计是产品抄袭的= ...

  6. 在android中用跑马灯的效果显示textview

    大家好,在我们通常的android project中,通常需要用到textview这一个布局文件,并且对于这一个显示布局所需要的文本文字内容. 下面我们就来介绍一种方法来实现在android中用跑马灯 ...

  7. 50个Android开发人员必备UI效果源码[转载]

    50个Android开发人员必备UI效果源码[转载] http://blog.csdn.net/qq1059458376/article/details/8145497 Android 仿微信之主页面 ...

  8. android中设置Animation 动画效果

    在 Android 中, Animation 动画效果的实现可以通过两种方式进行实现,一种是 tweened animation 渐变动画,另一种是 frame by frame animation ...

  9. Android 实现书籍翻页效果----升级篇

    自从之前发布了<Android 实现书籍翻页效果----完结篇 >之后,收到了很多朋友给我留言,前段时间由于事情较多,博客写得太匆忙很多细节地方没有描述清楚.所以不少人对其中的地方有不少不 ...

随机推荐

  1. 【python标准库模块二】random模块学习

    random模块是用来生成随机数的模块 导入random模块 import random 生成一个0~1的随机数,浮点数 #随机生成一个0~1的随机数 print(random.random()) 生 ...

  2. 焦点轮播图(tab轮播)

    主要有两部分:1.列表导航(小图片) 2.展示区(大图片) 页面布局: HTML部分:    <div class="s_conC">                  ...

  3. 虚拟机访问互联网的方法 -- 以RedHat系为例

    在虚拟机的三种网络模式中(Host-Only.桥接.NAT),能够实现虚拟机访问互联网的只有桥接与NAT模式,而Host-only主能实现虚拟机与主机两者间的通信.下面以RedHat系虚拟机系统为例, ...

  4. 使用Spring实现定时任务

    一.分类 从实现的技术上来分类,目前主要有三种技术(或者说有三种产品): Java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务.使用这种方式可 ...

  5. 安卓开发遇到Error:Execution failed for task ':app:transformClassesWithDexForDebug'.

    问题如下: Error:Execution failed for task ':app:transformClassesWithDexForDebug'. com.android.build.api. ...

  6. Docker Volume 之权限管理(一)

    摘要: Volume数据卷是Docker的一个重要概念.数据卷是可供一个或多个容器使用的特殊目录,可以为容器应用存储提供有价值的特性.然而Docker数据卷的权限管理经常是非常令人困惑的.本文将结合实 ...

  7. Android新建工程步骤(AndroidStudio)

    1.在 Android Studio 中,创建新项目: 如果您未打开项目,请在 Welcome to Android Studio 窗口中,点击 Start a new Android Studio ...

  8. Dynamics CRM 窗体Javascript获取时间字段值的准确转换

    本篇延续上篇博文继续时间字段的转化实验,本篇讲的是在窗体Javascript中获取及更新时间字段的具体写法,是否需要进行时制的转化,先看下通过ODATA取到的时间字段值 当然取出来看格式就知道是不能直 ...

  9. Simple tutorial for using TensorFlow to compute a linear regression

    """Simple tutorial for using TensorFlow to compute a linear regression. Parag K. Mita ...

  10. input事件--->按键事件的基本实现

    本程序基于TINY4412开发板,程序已经验证过,完全正确: 那么,如何来写这样的一个驱动程序呢? 1.分配一个input_dev结构体 2.设置 3.注册 4.硬件相关的代码,比如中断,定时器,休眠 ...