目录
·官方文档:http://developer.android.com/reference/android/support/v7/widget/RecyclerView.html
Class OverView
用于大量的data set填充于有限屏幕的一种可灵活的View。
Glossary of terms
Adapter:RecyclerView.Adapter的子类用于提供代表一个data set的item的View。
Position: 一个 data item在 Adapter中的position。
Index: 通过getChildAt(int)方法获得附加子类view的Index。和position不同。
Binding: 在adapter中使子类view能在对应position显示数据的过程。
Recycle (view):一个以前在特定的adapter position显示data的view可能被放置在缓存中用于稍后回收去再一次展示相应的数据。因为优化了初始、填充或者构造layout,这能大幅提升浏览效果。
Scrap (view):在 layout中处于临时分离状态的一个子类view。 Scrap views不用变成完全分离与父RecyclerView的view而被回收,如果被认为是dirty也可以没由adapter重新绑定或者修改而保持不变。
Dirty (view): 在展示前必须由adapter重新绑定的一个子类view。
Positions in RecyclerView:
RecyclerView 是一种RecyclerView.Adapter和RecyclerView.LayoutManager的抽象,可以在一批layout中展示data set变化。这样节省了LayoutManager去跟踪数据变化来计算动画。因为所有的view的binding是同时的,避免了非必要的绑定同样优化了效果。
基于这样的原因,在RecyclerView中有两种相关类型的position:
layout position: 一个item在最新的layout中的position。这个position是就LayoutManager而言的。
adapter position:item在Adapter中的position 。 这个 position 是就Adapter而言的。
这两个position除了在分发 adapter.notify* 事件和计算更新后的layout这两个情况之外是一样的。 返回和接收 *LayoutPosition* 的方法用position作为最新的layout的计(e.g. getLayoutPosition(), findViewHolderForAdapterPosition(int)). 这些方法在最新的layout计算中包含着所有的变化。可以认为这些positions和使用者正在看的positions是一致的。例如,如果使用者正在看屏幕上的列表,并且选中那个其中的第5条元素,符合使用者的所需元素的方法都在*AdapterPosition*中。(e.g. getAdapterPosition(), findViewHolderForAdapterPosition(int))你可能会用到这些方法当你要更新 adapter positions 时,即使它们还没有反馈给你layout。例如,当你在ViewHolder点击,就应该用到 getAdapterPosition().注意如果notifyDataSetChanged()已经被调用并且新的layout还没有被计算出来,这些方法可能没有计算adapter positions 。基于这个原因,要谨慎处理这些方法的NO_POSITION或者null 结果。
当写一个 RecyclerView.LayoutManager 你最想使用layout positions ,而当写一个RecyclerView.Adapter, 你最想使用adapter positions.
实现
·RecyclerViewMainActivity.java
public class RecyclerViewMainActivity extends Activity implements RecyclerView.OnItemTouchListener {
RecyclerView recyclerView;
RecyclerViewAdapter recyclerViewAdapter;
GestureDetectorCompat gestureDetectorCompat;
private ArrayList<VideoInfo> items;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView=(RecyclerView)findViewById(R.id.recyclerView);
/*set LinearLayoutManager*/
LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
linearLayoutManager.scrollToPosition(0);
recyclerView.setLayoutManager(linearLayoutManager);
items = new ArrayList<VideoInfo>();
for(int i =1;i<21;i++){
VideoInfo videoInfo = new VideoInfo();
// videoInfo.setImage_url("http://r2.ykimg.com/05100000549BB7E86714C02C98035672");
videoInfo.setTitle("this is a 中文"+i);
videoInfo.setSub_title("123456"+i);
items.add(videoInfo);
}
recyclerViewAdapter=new RecyclerViewAdapter(getApplication(),items);
recyclerView.setAdapter(recyclerViewAdapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {
return false;
}
@Override
public void onTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {
}
public class VideoInfo{
public boolean bTitle = false ;
public String image_url = "" ;
public String title = "" ;
public String sub_title ="" ;
public String getSub_title() {
return sub_title;
}
public void setSub_title(String sub_title) {
this.sub_title = sub_title;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getImage_url() {
return image_url;
}
public void setImage_url(String image_url) {
this.image_url = image_url;
}
}
}
·RecyclerViewAdapter.java
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ListItemViewHolder> {
private List<RecyclerViewMainActivity.VideoInfo> items;
private Context mContext;
private ImageLoader imageLoader = ImageLoader.getInstance();
RecyclerViewAdapter(Context context, ArrayList<RecyclerViewMainActivity.VideoInfo> modelData) {
if (modelData == null) {
throw new IllegalArgumentException("modelData must not be null");
}
items = modelData;
mContext = context;
}
@Override
public ListItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View itemView = LayoutInflater.
from(viewGroup.getContext()).
inflate(R.layout.history_list_item, viewGroup, false);
return new ListItemViewHolder(itemView);
}
@Override
public void onBindViewHolder(ListItemViewHolder viewHolder, int position) {
RecyclerViewMainActivity.VideoInfo info = items.get(position);
imageLoader.init(ImageLoaderConfiguration.createDefault(mContext));
if (info != null) {
viewHolder.mTitle.setText(info.title);
viewHolder.releaseChannel.setText(info.sub_title);
viewHolder.playedTimes.setText(info.sub_title);
imageLoader.displayImage(info.image_url, viewHolder.mThumbnail);
}
}
@Override
public int getItemCount() {
return items.size();
}
public final static class ListItemViewHolder extends RecyclerView.ViewHolder {
public TextView mTitle;
public ImageView mThumbnail;
public TextView releaseChannel, playedTimes;
public ListItemViewHolder(View itemView) {
super(itemView);
mThumbnail = (ImageView) itemView.findViewById(R.id.thumbnail);
mTitle = (TextView) itemView.findViewById(R.id.history_item_title);
releaseChannel = (TextView) itemView.findViewById(R.id.release_channel);
playedTimes = (TextView) itemView.findViewById(R.id.played_times);
}
}
}
·activity_main.xml
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".RecyclerViewMainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
·history_list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/history_list_item_outer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/all_padding_l"
android:paddingBottom="@dimen/all_padding_l"
android:paddingLeft="@dimen/all_padding_xl"
android:paddingRight="@dimen/all_padding_xl"
android:background="@color/white">
<RelativeLayout
android:id="@+id/item_poster_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/thumbnail"
android:layout_width="130dp"
android:layout_height="wrap_content"
android:scaleType="fitStart"
/>
<TextView
android:id="@+id/stripe_top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@id/thumbnail"
android:layout_alignRight="@+id/thumbnail"
android:layout_marginBottom="@dimen/all_padding_l"
android:layout_marginRight="@dimen/all_padding_l"
android:background="@color/black"
android:gravity="center"
android:maxLines="1"
android:padding="@dimen/all_padding_s"
android:text="10:30"
android:textColor="@color/white"
android:visibility="gone" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/item_description_outer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/item_poster_layout"
android:layout_marginLeft="12dp"
android:layout_toRightOf="@id/item_poster_layout">
<TextView
android:id="@+id/history_item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
android:textColor="@color/title_color"
android:textSize="15sp" />
<RelativeLayout
android:id="@+id/item_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/history_item_title"
android:layout_below="@+id/history_item_title">
<ImageView
android:id="@+id/history_item_devicetype"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true" />
<TextView
android:id="@+id/release_channel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/all_padding_s"
android:layout_toRightOf="@id/history_item_devicetype"
android:textColor="@color/sub_title_color" />
<TextView
android:id="@+id/played_times"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/release_channel"
android:layout_marginTop="1dp"
android:textColor="@color/sub_title_color"
android:textSize="12sp" />
</RelativeLayout>
<TextView
android:id="@+id/history_item_play_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone" />
</RelativeLayout>
<FrameLayout
android:id="@+id/edit_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
>
<ImageView
android:id="@+id/img_space_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
<ImageView
android:id="@+id/item_delete_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginRight="5dp" />
</FrameLayout>
</RelativeLayout>