介绍三个Android支持库控件:TabLayout+ViewPager+RecyclerView
本文主要介绍如下三个Android支持库控件的配合使用:
- TabLayout:android.support.design.widget.TabLayout
- ViewPager:android.support.v4.view.ViewPager
- RecyclerView:android.support.v7.widget.RecyclerView
对于支持库的使用,这里稍作介绍:
Android支持库包含常用的v4、v7、v13以及v17,注解支持(annotation),设计支持(material design)等。
目前v4和v7已经根据不同的功能进行了拆分,以减小目标Apk的大小,可针对某项具体的功能引入特定的包,而不用整体引入support-v4
包。
比如,以下为笔者常用的支持库,读者可以参考:
// 实现各种 UI 相关组件,例如 ViewPager、NestedScrollView 和 ExploreByTouchHelper。
supportCoreUi : 'com.android.support:support-core-ui:24.2.0',
// 添加对使用片段封装用户界面和功能的支持,从而使应用能够提供可以在大屏幕设备与小屏幕设备之间进行调节的布局。
// 此模块依赖于 compat、core-utils、core-ui 和 media-compat。
supportFragment : 'com.android.support:support-fragment:24.2.0',
// 此库添加了对操作栏用户界面设计模式的支持。此库包含对 Material Design 用户界面实现的支持。
supportAppCompat : 'com.android.support:appcompat-v7:24.2.0',
// recyclerview 库添加了 RecyclerView 类。此类能够为 RecyclerView 小部件提供支持,
// RecyclerView 是一种通过提供有限的数据项窗口有效显示大数据集的视图。
supportRecyclerView : 'com.android.support:recyclerview-v7:24.2.0',
// 此库添加了对 CardView 小部件的支持,让您能够在卡片内显示信息,从而使应用具备一致的外观。
supportCardView : 'com.android.support:cardview-v7:24.2.0',
// 注解软件包提供的 API 支持向应用中添加注解元数据。
supportAnnotations : 'com.android.support:support-annotations:24.2.0',
// 设计软件包提供的 API 支持向应用中添加 Material Design 组件和模式。
supportDesign : 'com.android.support:design:24.2.0',
最后,需要注意,支持库的版本需要保持一致,不然容易出现编译错误。
更多关于支持库的使用,请参考官方文档。
先上效果图:
(左滑的比较慢,是为了看清效果)
一、TabLayout
TabLayout是design支持库中引入的支持Tab页的控件,配合ViewPager使用,实现Table页面的滑动。使用时:
- 使用
setTabMode(TabLayout.MODE_FIXED)
来设置TabLayout的模式; - 通过
addTab
来添加Tab页面; - 最后通过
setupWithViewPager
来关联ViewPager.
// 设置TabLayout的模式
goodsTypeTl.setTabMode(TabLayout.MODE_FIXED);
// 添加Fragment显示
for (int i = 0; i < 2; i++) {
PickingTaskGoodsFragment itemFragment = PickingTaskGoodsFragment.newInstance(
i == 0 ? unCompletedPickingSku : pickingCompletedSku);
fragmentList.add(itemFragment);
goodsTypeTl.addTab(goodsTypeTl.newTab().setText(titleList.get(i)));
}
// 实例化ViewPage的适配器
FragmentPagerAdapter fAdapter = new PickingFragmentPagerAdapter(
getSupportFragmentManager(), fragmentList, titleList);
// viewpager加载adapter
goodsDetailVp.setAdapter(fAdapter);
// TabLayout加载viewpager
goodsTypeTl.setupWithViewPager(goodsDetailVp);
二、ViewPager
ViewPager是在v4包中引入的控件,在布局文件中,紧接着TabLayout
进行布局。ViewPager继承自ViewGroup,在使用时,最关键的是为其添加PagerAdapter,一般ViewPage会包含Fragment,那么这里PagerAdapter会使用FragmentPagerAdapter:
public abstract class FragmentPagerAdapter extends PagerAdapter
FragmentPagerAdapter是一个抽象类,在使用时一般继承自FragmentPagerAdapter自定义实现:
public class PickingFragmentPagerAdapter extends FragmentPagerAdapter {
private List<Fragment> fragmentList;
private List<String> titleList;
public PickingFragmentPagerAdapter(FragmentManager fm,
List<Fragment> fragmentList, List<String> titleList) {
super(fm);
this.fragmentList = fragmentList;
this.titleList = titleList;
}
@Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
@Override
public int getCount() {
return titleList.size();
}
@Override
public CharSequence getPageTitle(int position) {
return titleList.get(position);
}
}
getItem和getCount方法必须要求实现,分别返回List<Fragment>
的内容就行了。
在实例化PickingFragmentPagerAdapter时,需要传入FragmentManager,一般采用getSupportFragmentManager()。
三、RecyclerView
RecyclerView是v7支持库中引入的控件,使用时需要依赖com.android.support:recyclerview-v7:22.2.1
,使用RecyclerView需要注意两点:
- 设置LayoutManager
recyclerView.setLayoutManager(new LinearLayoutManager(context));
当然,这里还可以设置GridLayoutManager
。
2. 设置Adapter
recyclerView.setAdapter(new PickingTaskGoodsAdapter(pickingTaskDParams, mListener));
RecyclerView的Adapter是需要重点关注的。其中,需要实现的方法有三个:onCreateViewHolder
、onBindViewHolder
和getItemCount
。
- onCreateViewHolder:这个方法的返回值是ViewHolder,而这个ViewHolder一般都需要自定义,当然,默认RecyclerView也有ViewHolder。
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.out_picking_goods_detail_item, parent, false);
return new ViewHolder(view, new MySkuItemData());
View是直接通过Inflater提取出来的(注意item的根ViewGroup的height不能设置为match parent,不然多行item无法正常显示),ViewHolder的入参需要传入View。ViewHolder的定义有点讲究,与ListView中有不一致:
public class ViewHolder extends RecyclerView.ViewHolder {
final View mView;
AutofitTextView goodsNumberTv;
TextView goodsNameTv;
TextView goodsLeftNumberTv;
ImageView skuState;
Button pickingSku;
ViewHolder(View view) {
super(view);
mView = view;
goodsNumberTv = (AutofitTextView) view.findViewById(R.id.out_picking_task_goods_number_tv);
goodsNameTv = (TextView) view.findViewById(R.id.out_picking_task_goods_name_tv);
goodsLeftNumberTv = (TextView) view.findViewById(R.id.out_picking_task_goods_left_number_tv);
skuState = (ImageView) view.findViewById(R.id.out_picking_task_goods_sku_state_iv);
pickingSku = (Button) view.findViewById(R.id.out_picking_task_goods_picking_btn);
}
}
首先,需要定义一个带参构造器,第一个参数一定是View,ViewHolder也需要包含View的域,另外,ViewHolder可以包含各个View的监听器,而这种监听器一般都需要自定义,因为其中会包含重要的参数。
- onBindViewHolder是具体实现数据更新的地方,onBindViewHolder的入参为
ViewHolder holder, int position
,因此,首先通过position获取数据,然后对ViewHolder的控件依次设置:
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
PickingTaskDParam dParam = taskDParamList.get(position);
holder.goodsNumberTv.setText(dParam.getSkuNo());
holder.goodsNameTv.setText(dParam.getSkuName());
holder.goodsLeftNumberTv.setText(String.valueOf(dParam.getPlannedPickQty().intValue()));
if (dParam.getOptStatus() == 1 || dParam.getOptStatus() == 2) {
// 大小设置
holder.pickingSku.setVisibility(View.GONE);
holder.skuState.setVisibility(View.VISIBLE);
} else {
holder.skuState.setVisibility(View.GONE);
if (pickingVisible) {
holder.pickingSku.setVisibility(View.VISIBLE);
holder.pickingSku.setOnClickListener(new MyItemOnClickListener(dParam));
} else {
holder.pickingSku.setVisibility(View.GONE);
}
}
}
- getItemCount就直接返回数据List的size()就可以啦。
RecyclerView添加分割:分为设置垂直方向距离和设置分隔条两种方式:
垂直方向距离:
public class VerticalSpaceItemDecoration extends RecyclerView.ItemDecoration {
private final int verticalSpaceHeight;
public VerticalSpaceItemDecoration(int verticalSpaceHeight) {
this.verticalSpaceHeight = verticalSpaceHeight;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
RecyclerView.State state) {
outRect.bottom = verticalSpaceHeight;
}
}
分隔条:
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
private Drawable divider;
/**
* Default divider will be used
*/
public DividerItemDecoration(Context context) {
final TypedArray styledAttributes = context.obtainStyledAttributes(ATTRS);
divider = styledAttributes.getDrawable(0);
styledAttributes.recycle();
}
/**
* Custom divider will be used
*/
public DividerItemDecoration(Context context, int resId) {
divider = ContextCompat.getDrawable(context, resId);
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
int top = child.getBottom() + params.bottomMargin;
int bottom = top + divider.getIntrinsicHeight();
divider.setBounds(left, top, right, bottom);
divider.draw(c);
}
}
}
以上关于分隔条内容可参考Stack Overflow:How to add dividers and spaces between items in RecyclerView?
四、One more thing
最后,复习下Fragment和Activity的数据传递:
- 从Activity到Fragment:Bundle,通过Fragment的newInstance方法:
public static PickingTaskGoodsFragment newInstance(List<PickingTaskDParam> pickingTaskDParams) {
PickingTaskGoodsFragment fragment = new PickingTaskGoodsFragment();
Bundle args = new Bundle();
args.putParcelable(PICKING_TASK_D_PARAM, Parcels.wrap(pickingTaskDParams));
fragment.setArguments(args);
return fragment;
}
- 从Fragment到Activity:接口回调,在Fragment中定义接口,让包含该Fragment的Activity必须实现接口:
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnListFragmentInteractionListener) {
mListener = (OnListFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnListFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnListFragmentInteractionListener {
void onListFragmentInteraction(PickingTaskDParam item);
}
以上。
介绍三个Android支持库控件:TabLayout+ViewPager+RecyclerView的更多相关文章
- 【ALearning】第三章 Android基本常见控件
本章主要介绍主要的寻常较多使用的控件,包含TextView.EditView.ImageView.Button等.本章将介绍相关控件基本属性的使用,为以后章节的进阶学习提供基础.案例中引用的Linea ...
- 使用Android Support Design 控件TabLayout 方便快捷实现选项卡功能
1.概述 TabLayout是在2015年的google大会上,google发布了新的Android Support Design库的新组件之一,以此来全面支持Material Design 设计风格 ...
- Android 中常见控件的介绍和使用
1 TextView文本框 1.1 TextView类的结构 TextView 是用于显示字符串的组件,对于用户来说就是屏幕中一块用于显示文本的区域.TextView类的层次关系如下: java.la ...
- Android Material Design控件学习(三)——使用TextInputLayout实现酷市场登录效果
前言 前两次,我们学习了 Android Material Design控件学习(一)--TabLayout的用法 Android Material Design控件学习(二)--Navigation ...
- 【转】Android M新控件之AppBarLayout,NavigationView,CoordinatorLayout,CollapsingToolbarLayout的使用
Android M新控件之AppBarLayout,NavigationView,CoordinatorLayout,CollapsingToolbarLayout的使用 分类: Android UI ...
- 【转】Android M新控件之FloatingActionButton,TextInputLayout,Snackbar,TabLayout的使用
Android M新控件之FloatingActionButton,TextInputLayout,Snackbar,TabLayout的使用 分类: Android UI2015-06-15 16: ...
- 【风马一族_Android】第4章Android常用基本控件
第4章Android常用基本控件 控件是Android用户界面中的一个个组成元素,在介绍它们之前,读者必须了解所有控件的父类View(视图),它好比一个盛放控件的容器. 4.1View类概述 对于一个 ...
- Android 一个日历控件的实现代码
转载 2017-05-19 作者:Othershe 我要评论 本篇文章主要介绍了Android 一个日历控件的实现代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看 ...
- Android自己定义控件系列二:自己定义开关button(一)
这一次我们将会实现一个完整纯粹的自己定义控件,而不是像之前的组合控件一样.拿系统的控件来实现.计划分为三部分:自己定义控件的基本部分,自己定义控件的触摸事件的处理和自己定义控件的自己定义属性: 以下就 ...
随机推荐
- 微信公众平台开发-OAuth2.0网页授权(含源码)
微信公众平台开发-OAuth2.0网页授权接口.网页授权接口详解(含源码)作者: 孟祥磊-<微信公众平台开发实例教程> 在微信开发的高级应用中,几乎都会使用到该接口,因为通过该接口,可以获 ...
- 最强 IDE Visual Studio 2017 正式版发布
Visual Studio 2017 正式版发布,该版本不仅添加了实时单元测试.实时架构依赖关系验证等新特性,还对许多实用功能进行了改进,如代码导航.IntelliSense.重构.代码修复和调试等等 ...
- Asp.Net 常用工具类之Office—Excel导入(5)
之前在做一个项目的时候,客户方面只提供了一份简单的Excel文件,且要跟现有数据进行对接. 当时想到的是如果数据量不大,可以Excel一条一条加进去,无奈数据有几十兆!!! 换了一种思维,进行了导入: ...
- 第二章 mac上运行第一个appium实例
一.打开appium客户端工具 1 检查环境是否正常运行: 点击左边第三个图标 这是测试你环境是否都配置成功了 2 执行的过程中,遇到Could not detect Mac OS ...
- html表单 2017-03-10PM
在写表单之前补充一点:网页名以及属性的值命名都不能用中文,尽量用英文或拼音. html表单特写 1.表单格式 <form method="get/post" action=& ...
- Repcached实现memcached复制
1.介绍 repcached是日本人开发的实现memcached复制功能,它是一个单 master单 slave的方案,但它的master/slave都是可读写的,而且可以相互同步,如果 ma ...
- JavaWeb之Servlet总结
今天上班居然迟到了,昨天失眠了,看完吐槽大会实在不知道做些什么,刚好朋友给我发了两个JavaWeb的练习项目,自己就又研究了下,三四点才睡,可能周日白天睡的太多了,早上醒来已经九点多了,立马刷牙洗脸头 ...
- JavaWeb之Filter过滤器
原本计划这一篇来总结JSP,由于JSP的内容比较多,又想着晚上跑跑步减减肥,所以今天先介绍Filter以及它的使用举例,这样的话还有些时间可以锻炼锻炼.言归正传,过滤器从字面理解她的话有拦网.过滤的功 ...
- .Net程序员学用Oracle系列(22):分析函数(OVER)
1.函数语法 1.1.语法概述 1.2.窗口详解 1.2.1.ROWS 窗口 1.2.2.RANGE 窗口 2.函数用法 2.1.普通统计类函数 2.2.数据排序类函数 2.3.数据分布类函数 2.4 ...
- 【转】nginx配置:location配置方法及实例详解
location匹配的是nginx的哪个变量? $request_uri location的匹配种类有哪些? 格式 location [ 空格 | = | ~ | ~* | !~ | !~* ] /u ...