RecyclerView
先加入依赖:
compile 'com.android.support:recyclerview-v7:26.0.0-alpha1'
在布局中:
<android.support.v7.widget.RecyclerView android:id="@+id/recycleview_message" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v7.widget.RecyclerView>
接着写一个Bean,即列表中的单位项:
public class MyMessage { private byte[] image_friend; private String name_friend; private String content; MyMessage(String name, String content, byte[] image){ this.name_friend = name; this.content = content; this.image_friend = image; } public String getFriendName(){ return name_friend; } public String getContent(){ return content; } public byte[] getFriendImage(){ return image_friend; } }
接着编写其适配器:
public class RVAdapterMessage extends RecyclerView.Adapter<RVAdapterMessage.ViewHolder> { private List<MyMessage> myMessageList; static class ViewHolder extends RecyclerView.ViewHolder { View itemview_message; ImageView imageview_image; TextView textview_name; TextView textview_content; public ViewHolder(View view) { super(view); itemview_message = view; imageview_image = (ImageView)view.findViewById(R.id.message_friendimage); textview_name = (TextView)view.findViewById(R.id.message_friendname); textview_content = (TextView)view.findViewById(R.id.message_content); } } public RVAdapterMessage(List<MyMessage> myMessageList) { this.myMessageList = myMessageList; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.message_item, parent, false); final ViewHolder holder = new ViewHolder(view); holder.itemview_message.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position = holder.getAdapterPosition(); MyMessage temp_mymessage = myMessageList.get(position); Toast.makeText(v.getContext(), "you clicked view " + temp_mymessage.getFriendName(), Toast.LENGTH_SHORT).show(); } }); holder.itemview_message.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { int position = holder.getAdapterPosition(); MyMessage temp_mymessage = myMessageList.get(position); Toast.makeText(v.getContext(), "you clicked view " + temp_mymessage.getFriendName(), Toast.LENGTH_SHORT).show(); return true; } }); return holder; } //这个方法主要用于适配渲染数据到View中 @Override public void onBindViewHolder(ViewHolder holder, int position) { MyMessage tempmessage = myMessageList.get(position); byte[] bitmapdata = tempmessage.getFriendImage(); Bitmap bitmap = BitmapFactory.decodeByteArray(bitmapdata, 0, bitmapdata.length); holder.imageview_image.setImageBitmap(bitmap); holder.textview_name.setText(tempmessage.getFriendName()); holder.textview_content.setText(tempmessage.getContent()); } //BaseAdapter的getCount方法了,即总共有多少个条目 @Override public int getItemCount() { return myMessageList.size(); } public void setNewData(List<MyMessage> myMessageList){ this.myMessageList = myMessageList; } }
最后,就可以在主界面的java中:
List<MyMessage> myMessageList = new ArrayList<MyMessage>(); //myMessageList.add(...) RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view); // 设置布局管理器 //瀑布流,设置为3列 StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL); /*// 设置布局管理器 //垂直分布和横向分布 LinearLayoutManager.HORIZONTAL VERTICAL LinearLayoutManager layoutManager = new LinearLayoutManager(this); layoutManager.setOrientation(LinearLayoutManager.VERTICAL);*/ recyclerView.setLayoutManager(layoutManager); RVAdapterMessage adapter = new RVAdapterMessage(myMessageList); recyclerView.setAdapter(adapter);
下面是RecyclerView的其他用法:
从底部开始加载数据:
linearLayoutManager.setStackFromEnd(true);
指定view的类型:
@Override public int getItemViewType(int position) { return position; }
调到指定位置:
private void smoothMoveToPosition(RecyclerView mRecyclerView, final int position) { // 第一个可见位置 int firstItem = mRecyclerView.getChildLayoutPosition(mRecyclerView.getChildAt(0)); // 最后一个可见位置 int lastItem = mRecyclerView.getChildLayoutPosition(mRecyclerView.getChildAt(mRecyclerView.getChildCount() - 1)); if (position < firstItem) { // 如果跳转位置在第一个可见位置之前,就smoothScrollToPosition可以直接跳转 mRecyclerView.smoothScrollToPosition(position); } else if (position <= lastItem) { // 跳转位置在第一个可见项之后,最后一个可见项之前 // smoothScrollToPosition根本不会动,此时调用smoothScrollBy来滑动到指定位置 int movePosition = position - firstItem; if (movePosition >= 0 && movePosition < mRecyclerView.getChildCount()) { int top = mRecyclerView.getChildAt(movePosition).getTop(); mRecyclerView.smoothScrollBy(0, top); } } else { // 如果要跳转的位置在最后可见项之后,则先调用smoothScrollToPosition将要跳转的位置滚动到可见位置 // 再通过onScrollStateChanged控制再次调用smoothMoveToPosition,执行上一个判断中的方法 mRecyclerView.smoothScrollToPosition(position); } }
通常是对List进行添加或者删除,即在原数据上进行更新,则列表的更新方法为:
adapter.notifyDataSetChanged();
如果是要直接对List进行赋值,例如:myMessageList = myMessageList2;
adapter.setNewData(myFriendsList);
adapter.notifyDataSetChanged();
获取列表中某个单项View,这种方法只适用于列表长度不超出屏幕的情况:
private void getState(int position){
RVAdapterMessage.ViewHolder viewHolder = (RVAdapterMessage.ViewHolder)mRecyclerView.getChildViewHolder(mRecyclerView.getChildAt(position)); }
注意,Recycleview的getChildAt函数中的参数是以第一个可见的view为基准,比如列表总共有6个view,只有中间的4个显示在屏幕中,那么getChildAt(0)取得的是屏幕中显示的第一个,即6个中的第2个。
所以,要获得相应的view,可以先减去第一个可见的项的位置,或者像下面这样获取view:
View view = recyclerView.getLayoutManager().findViewByPosition(position);
另外,只能取到那些出现在屏幕中的view,比如上述例子中,如果想通过getChildAt(-1)或getChildAt(4)来取两边的view,是取不到的,会返回null。目前还没找到方法在列表中获取屏幕外的view。
检测Recycleview是否滑到了最下面:
recyclerView_square.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); LinearLayoutManager manager = (LinearLayoutManager) recyclerView.getLayoutManager(); // 当不滚动时 if (newState == RecyclerView.SCROLL_STATE_IDLE) { //获取最后一个完全显示的ItemPosition int lastVisibleItem = manager.findLastCompletelyVisibleItemPosition(); int totalItemCount = manager.getItemCount(); // 判断是否滚动到底部 if (lastVisibleItem == (totalItemCount - 1)) { //加载更多功能的代码 Log.d(TAG, "onScrollStateChanged: 加载更多"); } } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); //dx用来判断横向滑动方向,dy用来判断纵向滑动方向 } });
做聊天列表时需要倒置排序:
layoutManager.setReverseLayout(true);
顶部/底部是否可以再滑动?
canScrollVertically(1)
1表示底部;-1表示顶部
canScrollVertically(1)返回true,表示该控件还没滑到最底部