android 5.0新特性学习--RecyclerView

在过去很多年,我们的PC或者手机设备都是采用拟物化的设计风格,IOS采用扁平化的特性,android在2014年IO大会上说采用Material Design的设计风格,显示效果不能过于生硬的转换,而是平滑,过度的切换方式,避免线性的动画效果,而是代替以曲线的效果进行展示,并且所有的图标的动画切换都应该无缝化切换。

如果想深入了解材料设计即(material Design)的设计:

可以参看如下网址:http://design.1sters.com,尤其是android 应用的UED设计师们,可以看下:

开发中要在libs文件夹下面中加上android_support_v4.jar包

RecyclerView

java.lang.Object
  android.view.View
    android.view.ViewGroup
      android.support.v7.widget.RecyclerView

官网地址:https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html

RecyclerView 一个特点就是,将 layout 抽象成了一个 LayoutManager,RecylerView 不负责子 View 的布局, 我们可以自定义 LayoutManager 来实现不同的布局效果, 目前只提供了LinearLayoutManager。 LinearLayoutManager 可以指定方向,默认是垂直, 可以指定水平, 这样就轻松实现了水平的 ListView。

除了LinearLayoutManager还有其他两种布局管理器:

GridLayoutManager 网格的item
StaggeredGridLayoutManager 交错的网格item

当然也可以通过集成ResyclerView,layoutManager类来自定义自己的布局管理器。

RecyclerView的使用过程中会使用到一个Adapter:RecyclerView.Adapter,里面屏蔽了以前写BaseAdapter的中好多重读的代码的编写,将加载item布局放在onCreateViewHolder(ViewGroup viewGroup, int i)方法中,在onBindViewHolder(ViewHolder viewHolder, int i)中数据加载到item中。用于优化的viewHolder也是继承自RecyclerView.ViewHolder。

RecyclerView不提供setOnItemClickListener方法,你可以在ViewHolder中添加事件。

RecyclerView之间的分割线:

http://my.oschina.net/xesam/blog/351408

官网地址:https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html

关于使用可以参考:

http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0710/1631.html

http://blog.csdn.net/cym492224103/article/details/41719497

编写demo:

android 5.0新特性学习--RecyclerView

布局文件:

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.wangfubin.recyclerview.MainActivity"> <android.support.v7.widget.RecyclerView
android:id="@+id/id_recyclerview"
android:divider="#ffff0000"
android:dividerHeight="10dp"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
item_gridview.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="100dp"
xmlns:tool="http://schemas.android.com/tools"
android:background="#44ff0000"
android:layout_height="100dp"> <TextView
android:id="@+id/id_num"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
tool:text="1" />
</FrameLayout>
item_listview.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
xmlns:tool="http://schemas.android.com/tools"
android:background="#44ff0000"
android:layout_height="wrap_content"> <TextView
android:id="@+id/id_num"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
tool:text="1" />
</FrameLayout>
MainActivity.java
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast; import java.util.ArrayList;
import java.util.List; public class MainActivity extends AppCompatActivity { private RecyclerView mRecyclerView;
private List<String> mDatas;
private HomeAdapter mAdapter; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); initData();
mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview);
//垂直线性RecyclerView
//mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); //Grid布局
//mRecyclerView.setLayoutManager(new GridLayoutManager(this,4)); //瀑布流
//垂直方向
//mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.VERTICAL));
//水平方向
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.HORIZONTAL)); mRecyclerView.setAdapter(mAdapter = new HomeAdapter(getApplicationContext(),initData()));
//垂直线性RecyclerView分割线
//mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST)); //GridView的分隔线
mRecyclerView.addItemDecoration(new DividerGridItemDecoration(this));
//添加默认动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mAdapter.setOnItemClickLitener(new HomeAdapter.OnItemClickLitener() {
@Override
public void onItemClick(View view, int position) {
Toast.makeText(getApplicationContext(),"单击事件",Toast.LENGTH_SHORT).show();
} @Override
public void onItemLongClick(View view, int position) {
Toast.makeText(getApplicationContext(),"长按事件",Toast.LENGTH_SHORT).show();
}
}); } /**
* 初始化模拟数据
* @return
*/
protected List<String> initData() {
mDatas = new ArrayList<String>();
for (int i = 'A'; i < 'z'; i++) {
mDatas.add("" + (char) i);
}
return mDatas;
} @Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
} @Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{ case R.id.id_action_add:
//新增数据
mAdapter.addData(1);
break;
case R.id.id_action_delete:
//删除数据
mAdapter.removeData(1);
break;
}
return true;
} }

HomeAdapter.java

import java.util.List;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.widget.TextView; /**
* Created by wangfubin on 2016/11/12.
*/ class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.MyViewHolder>
{ private List<String> mDatas;
private LayoutInflater mInflater; public interface OnItemClickLitener
{
void onItemClick(View view, int position);
void onItemLongClick(View view , int position);
} private OnItemClickLitener mOnItemClickLitener; public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener)
{
this.mOnItemClickLitener = mOnItemClickLitener;
} public HomeAdapter(Context context, List<String> datas)
{
mInflater = LayoutInflater.from(context);
mDatas = datas;
} @Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
MyViewHolder holder = new MyViewHolder(mInflater.inflate(
R.layout.item_listview, parent, false));
return holder;
} @Override
public void onBindViewHolder(final MyViewHolder holder, final int position)
{
holder.tv.setText(mDatas.get(position)); // 如果设置了回调,则设置点击事件
if (mOnItemClickLitener != null)
{
holder.itemView.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
int pos = holder.getLayoutPosition();
mOnItemClickLitener.onItemClick(holder.itemView, pos);
}
}); holder.itemView.setOnLongClickListener(new OnLongClickListener()
{
@Override
public boolean onLongClick(View v)
{
int pos = holder.getLayoutPosition();
mOnItemClickLitener.onItemLongClick(holder.itemView, pos);
removeData(pos);
return false;
}
});
}
} @Override
public int getItemCount()
{
return mDatas.size();
} public void addData(int position)
{
mDatas.add(position, "Insert One");
notifyItemInserted(position);
} public void removeData(int position)
{
mDatas.remove(position);
notifyItemRemoved(position);
} class MyViewHolder extends ViewHolder
{ TextView tv; public MyViewHolder(View view)
{
super(view);
tv = (TextView) view.findViewById(R.id.id_num); }
}
}
DividerItemDecoration.java
/**
* 垂直水平分割线
*/
public class DividerItemDecoration extends RecyclerView.ItemDecoration { private static final int[] ATTRS = new int[]{
android.R.attr.listDivider
}; public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; private Drawable mDivider; private int mOrientation; public DividerItemDecoration(Context context, int orientation) {
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
setOrientation(orientation);
} public void setOrientation(int orientation) {
if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
throw new IllegalArgumentException("invalid orientation");
}
mOrientation = orientation;
} @Override
public void onDraw(Canvas c, RecyclerView parent) {
Log.v("recyclerview - itemdecoration", "onDraw()"); if (mOrientation == VERTICAL_LIST) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
} } public void drawVertical(Canvas c, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight(); final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(parent.getContext());
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
} public void drawHorizontal(Canvas c, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom(); final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
} @Override
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
if (mOrientation == VERTICAL_LIST) {
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
}
}
}
DividerGridItemDecoration.java
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.LayoutManager;
import android.support.v7.widget.RecyclerView.State;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.View; /**
*GridView分割线
* @author zhy
*
*/
public class DividerGridItemDecoration extends RecyclerView.ItemDecoration
{ private static final int[] ATTRS = new int[] { android.R.attr.listDivider };
private Drawable mDivider; public DividerGridItemDecoration(Context context)
{
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
} @Override
public void onDraw(Canvas c, RecyclerView parent, State state)
{ drawHorizontal(c, parent);
drawVertical(c, parent); } private int getSpanCount(RecyclerView parent)
{
// 列数
int spanCount = -1;
LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager)
{ spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
} else if (layoutManager instanceof StaggeredGridLayoutManager)
{
spanCount = ((StaggeredGridLayoutManager) layoutManager)
.getSpanCount();
}
return spanCount;
} public void drawHorizontal(Canvas c, RecyclerView parent)
{
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++)
{
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int left = child.getLeft() - params.leftMargin;
final int right = child.getRight() + params.rightMargin
+ mDivider.getIntrinsicWidth();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
} public void drawVertical(Canvas c, RecyclerView parent)
{
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++)
{
final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getTop() - params.topMargin;
final int bottom = child.getBottom() + params.bottomMargin;
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicWidth(); mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
} private boolean isLastColum(RecyclerView parent, int pos, int spanCount,
int childCount)
{
LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager)
{
if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
{
return true;
}
} else if (layoutManager instanceof StaggeredGridLayoutManager)
{
int orientation = ((StaggeredGridLayoutManager) layoutManager)
.getOrientation();
if (orientation == StaggeredGridLayoutManager.VERTICAL)
{
if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
{
return true;
}
} else
{
childCount = childCount - childCount % spanCount;
if (pos >= childCount)// 如果是最后一列,则不需要绘制右边
return true;
}
}
return false;
} private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,
int childCount)
{
LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager)
{
childCount = childCount - childCount % spanCount;
if (pos >= childCount)// 如果是最后一行,则不需要绘制底部
return true;
} else if (layoutManager instanceof StaggeredGridLayoutManager)
{
int orientation = ((StaggeredGridLayoutManager) layoutManager)
.getOrientation();
// StaggeredGridLayoutManager 且纵向滚动
if (orientation == StaggeredGridLayoutManager.VERTICAL)
{
childCount = childCount - childCount % spanCount;
// 如果是最后一行,则不需要绘制底部
if (pos >= childCount)
return true;
} else
// StaggeredGridLayoutManager 且横向滚动
{
// 如果是最后一行,则不需要绘制底部
if ((pos + 1) % spanCount == 0)
{
return true;
}
}
}
return false;
} @Override
public void getItemOffsets(Rect outRect, int itemPosition,
RecyclerView parent)
{
int spanCount = getSpanCount(parent);
int childCount = parent.getAdapter().getItemCount();
if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行,则不需要绘制底部
{
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
} else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列,则不需要绘制右边
{
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else
{
outRect.set(0, 0, mDivider.getIntrinsicWidth(),
mDivider.getIntrinsicHeight());
}
}
}

效果:

android 5.0新特性学习--RecyclerView

上一篇:DEVOPS技术实践_11:Jenkins集成Sonar


下一篇:cocos2d-html5对话界面设计