Android TabLayout实现京东详情效果
google在2015的io大会上,给我们带来了更加详细的material design设计规范,同时,也给我们带来了全新的android design support library,在这个support库里面,google给我们提供了更加规范的md设计风格的控件。最重要的是,android design support library的兼容性更广,直接可以向下兼容到android 2.2。
这两天需要做一个仿京东详情的页面,上面的tab切换,以前都是自己写viewpager+fragment,或者indicator的深度定制,一直想尝试一下tablayout,于是就有了下面的坑。
然后下面是我简单的实现效果(个人觉得很坑,还不如自己自定义的导航器)
添加引用库
dependencies { compile filetree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:24.2.0' compile 'com.android.support:design:24.2.0' compile 'com.android.support:recyclerview-v7:24.2.0' compile 'com.android.support:cardview-v7:24.2.0' }
toolbar与tablayout
我们来看一下实现的布局:
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <linearlayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/c12" android:gravity="center_vertical" android:minheight="45dp" android:orientation="horizontal" android:paddingleft="15dp" android:paddingright="15dp"> <imageview android:id="@+id/back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/back_icon" /> <linearlayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="horizontal"> <android.support.design.widget.tablayout android:id="@+id/tablayout" android:layout_width="match_parent" android:layout_height="match_parent" app:tabtextappearance="@style/tablayouttextstyle" app:tabgravity="center" app:tabmode="fixed" app:tabtextcolor="@color/c7" app:tabselectedtextcolor="@color/c8"/> </linearlayout> <imageview android:id="@+id/toolbar_more" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginleft="10dp" android:background="@drawable/more_icon" /> </linearlayout> <view style="@style/horizontal_line" /> <android.support.v4.view.viewpager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> <view style="@style/horizontal_line" /> <linearlayout android:layout_width="match_parent" android:layout_height="48dp" android:background="@color/c12" android:orientation="horizontal"> <linearlayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1"> <textview android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="收藏" android:textsize="10sp" /> <view style="@style/vertical_line" /> <textview android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="购物车" android:textsize="10sp" /> </linearlayout> <linearlayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1.5" android:background="@color/c8" android:gravity="center"> <textview style="@style/style_c12_s16" android:gravity="center" android:text="加入购物车" /> </linearlayout> </linearlayout> </linearlayout>
这布局文件最关键的一点就是android.support.design.widget.tablayout 标签中的app:tabmode=”scrollable”,他设置tab的模式为“可滑动的”。
其他的用法和indicator的用法差不多,都需要设置适配器,然后通过数据实现页面的适配。直接上代码
adapter
public class productdetailpageradapter extends fragmentpageradapter { private list<fragment> mfragments=null; private list<string> mtitles=null; public productdetailpageradapter(fragmentmanager fm, list<fragment> mfragments,list<string> mtitles) { super(fm); this.mfragments =mfragments; this.mtitles=mtitles; } public productdetailpageradapter(fragmentmanager fm, fragment... fragments) { super(fm); this.mfragments = arrays.aslist(fragments); } @override public fragment getitem(int position) { return mfragments.get(position); } @override public int getcount() { return mfragments.size(); } @override public charsequence getpagetitle(int position) { return mtitles.get(position); } }
主页面的相关逻辑,这里的fragment就是简单的fragment。
public class productdetailsactivity extends baseactivity { @bindview(r.id.viewpager) viewpager viewpager; @bindview(r.id.toolbar_more) imageview toolbarmore; @bindview(r.id.tablayout) tablayout tablayout; private list<fragment> mfragments; private string[] titles = new string[]{"商品", "详情"}; private productdetailpageradapter productpageradapter = null; private morepopupwindow popupwindow = null; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_product_details); butterknife.bind(this); init(); } private void init() { initviewpager(); } private void initviewpager() { mfragments = new arraylist<>(); mfragments.add(new productfragment()); mfragments.add(new productdetailfragment()); productpageradapter = new productdetailpageradapter(getsupportfragmentmanager(), mfragments, arrays.aslist(titles)); viewpager.setoffscreenpagelimit(2); viewpager.setadapter(productpageradapter); viewpager.setcurrentitem(1); tablayout.setupwithviewpager(viewpager); } @onclick(r.id.back) public void backclick() { finish(); } @onclick(r.id.toolbar_more) public void moreclick() { } private adapterview.onitemclicklistener onitemclicklistener = new adapterview.onitemclicklistener() { @override public void onitemclick(adapterview<?> parent, view view, int position, long id) { popupwindow.dismiss(); } }; public static void open(context context) { intent intent = new intent(context, productdetailsactivity.class); context.startactivity(intent); } }
上面的代码都比较简单不做过多的解释,在使用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的样式,然后通过引入
app:tabtextappearance=""
自定义icon添加到tab
当前的tablayout没有方法让我们去添加icon,我们可以使用spannablestring结合imagespan来实现
private int[] imageresid = { r.drawable.ic_one, r.drawable.ic_two, r.drawable.ic_three }; // ... @override public charsequence getpagetitle(int position) { // generate title based on item position // return tabtitles[position]; drawable image = context.getresources().getdrawable(imageresid[position]); image.setbounds(0, 0, image.getintrinsicwidth(), image.getintrinsicheight()); spannablestring sb = new spannablestring(" "); imagespan imagespan = new imagespan(image, imagespan.align_bottom); sb.setspan(imagespan, 0, 1, spannable.span_exclusive_exclusive); return sb; }
运行,发现没有显示,这是因为tablayout创建的tab默认设置textallcaps属性为true,这阻止了imagespan被渲染出来,可以通过下面的样式文件定义来改变:
<style name="mycustomtablayout" parent="widget.design.tablayout"> <item name="tabtextappearance">@style/mycustomtextappearance</item> </style> <style name="mycustomtextappearance" parent="textappearance.design.tab"> <item name="textallcaps">false</item> </style>
然后在getpagetitle方法中设置上有标题的tab
@override public charsequence getpagetitle(int position) { // generate title based on item position drawable image = context.getresources().getdrawable(imageresid[position]); image.setbounds(0, 0, image.getintrinsicwidth(), image.getintrinsicheight()); // replace blank spaces with image icon spannablestring sb = new spannablestring(" " + tabtitles[position]); imagespan imagespan = new imagespan(image, imagespan.align_bottom); sb.setspan(imagespan, 0, 1, spannable.span_exclusive_exclusive); return sb; }
tablayout还支持自定义view,通过gettabview来设置,这里就不讲怎么实现了,有兴趣的可以自行研究。
部分代码:https://github.com/xiangzhihong/jingdongapp
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。