标签:监听器 color gif OLE tab comm horizon encoding 实现
1. RecyclerView控件的基本使用,包括基础,进阶,高级部分,动画之类
2. RecyclerView控件的实战实例
3. RecyclerView控件集合AA(Android Annotations)注入框架实例
FastDev4Android框架项目地址:https://github.com/jiangqqlmj/FastDev4Android
1. 采用LayoutManager来处理Item的布局
2. 提供Item操作的默认动画,例如在增加或者删除item的时候
你也可以自定义LayoutManager或者设置添加/删除的动画,整体的RecyclerView结构图如下:
为了使用RecyclerView控件,我们需要创建一个Adapter和一个LayoutManager:
Adapter:继承自RecyclerView.Adapetr类,主要用来将数据和布局item进行绑定。
LayoutManager:布局管理器,设置每一项view在RecyclerView中的位置布局以及控件item view的显示或者隐藏。当View重用或者回收的时候,LayoutManger都会向Adapter来请求新的数据来进行替换原来数据的内容。这种回收重用的机制可以提供性能,避免创建很多的view或者是频繁的调用findViewById方法。这种机制和ListView还是很相似的。
1. LinearLayoutManager:线性布局,横向或者纵向滑动列表
2. GridLayoutManager:表格布局
3. StaggeredGridLayoutManager:流式布局,例如瀑布流效果
当然除了上面的三种内部布局之外,我们还可以继承RecyclerView.LayoutManager来实现一个自定义的LayoutManager。
Animations(动画)效果:
RecyclerView对于Item的添加和删除是默认开启动画的。我们当然也可以通过RecyclerView.ItemAnimator类定制动画,然后通过RecyclerView.setItemAnimator()方法来进行使用。
类名 | 说明 |
---|---|
RecyclerView.Adapter | 可以托管数据集合,为每一项Item创建视图并且绑定数据 |
RecyclerView.ViewHolder | 承载Item视图的子布局 |
RecyclerView.LayoutManager | 负责Item视图的布局的显示管理 |
RecyclerView.ItemDecoration | 给每一项Item视图添加子View,例如可以进行画分隔线之类的 |
RecyclerView.ItemAnimator | 负责处理数据添加或者删除时候的动画效果 |
dependencies {
…….
compile‘com.android.support:recyclerview-v7:23.1.1‘
}
<?xmlversionxmlversion="1.0" encoding="utf-8"?>
<LinearLayout xmlns:androidLinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"android:layout_width="match_parent"
android:layout_height="match_parent">
<includelayoutincludelayout="@layout/common_top_bar_layout"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView_one"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
></android.support.v7.widget.RecyclerView>
</LinearLayout>
public class RecyclerViewTestActivity extends AppCompatActivity {
private RecyclerView recyclerView_one;
private RecyclerView.Adapter mAdapter;
private LinearLayoutManager mLayoutManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//开始设置RecyclerView
recyclerView_one=(RecyclerView)this.findViewById(R.id.recyclerView);
//设置固定大小
recyclerView_one.setHasFixedSize(true);
//创建线性布局
mLayoutManager = new LinearLayoutManager(this);
//垂直方向
mLayoutManager.setOrientation(OrientationHelper.VERTICAL);
//给RecyclerView设置布局管理器
recyclerView_one.setLayoutManager(mLayoutManager);
//创建适配器,并且设置
mAdapter = new TestRecyclerAdapter(this);
recyclerView_one.setAdapter(mAdapter);
}
}
public class TestRecyclerAdapter extends RecyclerView.Adapter<TestRecyclerAdapter.ViewHolder>{
private LayoutInflater mInflater;
private String[] mTitles=null;
public TestRecyclerAdapter(Context context){
this.mInflater=LayoutInflater.from(context);
this.mTitles=new String[20];
for (int i=0;i<20;i++){
int index=i+1;
mTitles[i]="item"+index;
}
}
/**
* item显示类型
* @param parent
* @param viewType
* @return
*/
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view=mInflater.inflate(R.layout.item_recycler_layout,parent,false);
//view.setBackgroundColor(Color.RED);
ViewHolder viewHolder=new ViewHolder(view);
return viewHolder;
}
/**
* 数据的绑定显示
* @param holder
* @param position
*/
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.item_tv.setText(mTitles[position]);
}
@Override
public int getItemCount() {
return mTitles.length;
}
//自定义的ViewHolder,持有每个Item的的所有界面元素
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView item_tv;
public ViewHolder(View view){
super(view);
item_tv = (TextView)view.findViewById(R.id.item_tv);
}
}
}
这个自定义Adapter和我们在使用Listview时候的Adapter相比还是有点不太一样的,首先这边我们需要继承RecyclerView.Adaper类,然后实现两个重要的方法onBindViewHodler()以及onCreateViewHolder(),这边我们看出来区别,使用RecyclerView控件我们就可以把Item View视图创建和数据绑定这两步进行分来进行管理,用法就更加方便而且灵活了,并且我们可以定制打造千变万化的布局。同时这边我们还需要创建一个ViewHolder类,该类必须继承自RecyclerView.ViewHolder类,现在Google也要求我们必须要实现ViewHolder来承载Item的视图。
该Demo运行效果如下:
上面的例子我们这边比较简单使用LinearLayoutManager来实现了,其中布局是采用垂直布局的,当然我们还可以设置线性布局的方向为横向,只要如下设置即可:
mLayoutManager.setOrientation(OrientationHelper.HORIZONTAL);
运行效果如下:
GridLayoutManager girdLayoutManager=new GridLayoutManager(this,4);
recyclerView_one.setLayoutManager(girdLayoutManager);
运行效果如下:
StaggeredGridLayoutManager staggeredGridLayoutManager=new StaggeredGridLayoutManager(2,OrientationHelper.VERTICAL);
recyclerView_one.setLayoutManager(staggeredGridLayoutManager);
实现的是瀑布流的效果
RecyclerView.ItemDecoration | 给每一项Item视图添加子View,可以进行画分隔线之类的东西 |
---|
我们可以创建一个继承RecyclerView.ItemDecoration类来绘制分隔线,通过ItemDecoration可以让我们每一个Item从视觉上面相互分开来,例如ListView的divider非常相似的效果。当然像我们上面的例子ItemDecoration我们没有设置也没有报错哦,那说明ItemDecoration我们并不是强制需要使用,作为我们开发者可以设置或者不设置Decoration的。
实现一个ItemDecoration,系统提供的ItemDecoration是一个抽象类,内部除去已经废弃的方法以外,我们主要实现以下三个方法:
public static abstract class ItemDecoration {
public void onDraw(Canvas c,RecyclerView parent, State state) {
onDraw(c, parent);
}
public void onDrawOver(Canvas c,RecyclerView parent, State state) {
onDrawOver(c, parent);
}
public void getItemOffsets(RectoutRect, View view, RecyclerView parent, State state) {
getItemOffsets(outRect,((LayoutParams) view.getLayoutParams()).getViewLayoutPosition(),
parent);
}
}
又因为当我们RecyclerView在进行绘制的时候会进行绘制Decoration,那么会去调用onDraw和onDrawOver方法,那么这边我们其实只要去重写onDraw和getItemOffsets这两个方法就可以实现啦。然后LayoutManager会进行Item布局的时候,回去调用getItemOffset方法来计算每个Item的Decoration合适的尺寸
下面我们来具体实现一个Decoration:
TestDecoration.java
public class TestDecoration extends RecyclerView.ItemDecoration {
//采用系统内置的风格的分割线
private static final int[] attrs=newint[]{android.R.attr.listDivider};
private Drawable mDivider;
public TestDecoration(Context context) {
TypedArray typedArray=context.obtainStyledAttributes(attrs);
mDivider=typedArray.getDrawable(0);
}
/**
* 进行自定义绘制
* @param c
* @param parent
* @param state
*/
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
int top=parent.getPaddingTop();
intbottom=parent.getHeight()-parent.getPaddingBottom();
int childCount=parent.getChildCount();
for(int i=0;i<childCount;i++){
View child=parent.getChildAt(i);
RecyclerView.LayoutParams layoutParams=(RecyclerView.LayoutParams)child.getLayoutParams();
intleft=child.getRight()+layoutParams.rightMargin;
intright=left+mDivider.getIntrinsicWidth();
mDivider.setBounds(left,top,right,bottom);
mDivider.draw(c);
}
}
@Override
public void getItemOffsets(Rect outRect,View view, RecyclerView parent, RecyclerView.State state) {
outRect.set(0,0,mDivider.getIntrinsicWidth(),0);
}
}
- 我这边实例中采用系统主题(android.R.attr.listDivider)来设置成分隔线的,然后来获取尺寸,位置进行setBound(),绘制,接着通过outRect.set()来设置绘制整个区域范围,最后不要忘记往RecyclerView中设置该自定义的分割线:
//添加分割线
recyclerView_one.addItemDecoration(newTestDecoration(this));
运行效果大致如下:
上面的分割线效果只是垂直画了分割线,但是我们水平方向也要进行画分割线,那么我们下面对于自定义的Decoration进行改进:
AdvanceDecoration.java
/**
* 当前类注释:改进之后的自定义Decoration分割线
*/
public class AdvanceDecoration extends RecyclerView.ItemDecoration{
//采用系统内置的风格的分割线
private static final int[] attrs=newint[]{android.R.attr.listDivider};
private Drawable mDivider;
private int orientation;
public AdvanceDecoration(Contextcontext,int orientation) {
TypedArray typedArray=context.obtainStyledAttributes(attrs);
mDivider=typedArray.getDrawable(0);
typedArray.recycle();
this.orientation=orientation;
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
drawHDeraction(c,parent);
drawVDeraction(c,parent);
}
/**
* 绘制水平方向的分割线
* @param c
* @param parent
*/
private void drawHDeraction(Canvas c,RecyclerView parent){
int left=parent.getPaddingLeft();
intright=parent.getWidth()-parent.getPaddingRight();
int childCount=parent.getChildCount();
for(int i=0;i<childCount;i++){
View child=parent.getChildAt(i);
RecyclerView.LayoutParams layoutParams=(RecyclerView.LayoutParams)child.getLayoutParams();
inttop=child.getBottom()+layoutParams.bottomMargin;
intbottom=top+mDivider.getIntrinsicHeight();
mDivider.setBounds(left,top,right,bottom);
mDivider.draw(c);
}
}
/**
* 绘制垂直方向的分割线
* @param c
* @param parent
*/
private void drawVDeraction(Canvas c,RecyclerView parent){
int top=parent.getPaddingTop();
intbottom=parent.getHeight()-parent.getPaddingBottom();
int childCount=parent.getChildCount();
for(int i=0;i<childCount;i++){
View child=parent.getChildAt(i);
RecyclerView.LayoutParamsla youtParams=(RecyclerView.