花了一晚上的时间来研究RecyclerView的使用,现在将代码贴出,个人感觉RecyclerView相当强大,一定是以后布局的趋势,RecyclerView是5.0的新的库,其与ListView,GradView的设计思想不一样,自身也是有很多的优越性
1.RecyclerView关注点(不是关注点就是这个的效果要自己去设置)
仅关注回收与复用view,
不关注
Item的显示位置显示风格----LayoutManager
Item间的分隔------ItemDecoration
Item增加与删除的动画效果-----ItemAnimator
Adapter
ViewHolder
2.RecyclerView能干什么
实现ListView
实现GridView
横向ListView
横向GridView
瀑布流
定制Item增加与删除动画 (ItemAnimator)
3.使用前导包
android studio
导入jar包file->project structure->选中所用的medule->dependencis->"+"->选到v7的recyclerview包
eclipse
在sdk中extras下找到v7包导入项目即可
话不多说上代码
MainActivity.java
package cn.bigniu.recyclerviewdemo;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
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 SimpleAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化datas
initDatas();
//初始化View
initViews();
mAdapter=new SimpleAdapter(this,mDatas);
mRecyclerView.setAdapter(mAdapter);
/**
* 设置RecyclerView的布局管理
*
*
* ListView的显示方式
* LinearLayoutManager(Context context, int orientation, boolean reverseLayout)
*/
LinearLayoutManager linearLayoutManager=
new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
mRecyclerView.setLayoutManager(linearLayoutManager);
/**
* 为删除添加设置动画效果
*
* DefaultItemAnimator()为系统默认的动画效果
*
* Github上还有很多动画效果,可以自己下载下来使用,当然也可以自己定义
* github:https://github.com/gabrielemariotti/RecyclerViewItemAnimators
*/
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//点击事件回调
mAdapter.setmOnItemClickListener(new SimpleAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
Toast.makeText(MainActivity.this,
"Click:"+position,Toast.LENGTH_SHORT).show();
}
@Override
public void onItemLongClick(View view, int position) {
Toast.makeText(MainActivity.this,
"Long Click"+position,Toast.LENGTH_SHORT).show();
}
});
/**
* 设置RecyclerView的Item分割线
*
*void addItemDecoration(ItemDecoration)
* ItemDecoration是一个抽象类,系统也没有给我们提供一个实现类
* 所以这里我们使用网上的一个现成类
* 类的地址为:https://gist.github.com/alexfu/0f464fc3742f134ccdle
*
* 程序中的Divider其实就是从Theme中提取的listDivider方法
* 可通过DividerItemDecoration源码查看
*/
/*mRecyclerView.addItemDecoration(
new DividerItemDecoration(this,DividerItemDecoration.VERTICAL_LIST));*/
}
private void initViews() {
mRecyclerView= (RecyclerView) findViewById(R.id.id_recyclerView);
}
private void initDatas() {
mDatas=new ArrayList<String>();
for (int i='A';i<='z';i++){
mDatas.add(""+(char)i);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main,menu);
return true;
}
/**
* 在这里面就行点击menu后实现页面的改变操作
* @param item
* @return
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id=item.getItemId();
switch (id){
case R.id.action_add:
mAdapter.addData(1);
break;
case R.id.action_delete:
mAdapter.deleteData(1);
break;
case R.id.action_gridview:
mRecyclerView.setLayoutManager(new GridLayoutManager(this,3));
break;
case R.id.action_staggered:
Intent intent=new Intent(this,StaggeredActivity.class);
startActivity(intent);
break;
case R.id.action_hor_gridview:
mRecyclerView.setLayoutManager(
new StaggeredGridLayoutManager(5,StaggeredGridLayoutManager.HORIZONTAL));
break;
case R.id.action_listview:
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
}
SimpleAdapter.java(ListView,GridView)
package cn.bigniu.recyclerviewdemo;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
/**
* RecyclerView给开发者提供了一个Adapter,目的是为了让开发者强制使用ViewHolder
*/
public class SimpleAdapter extends RecyclerView.Adapter<SimpleAdapter.MyViewHolder>{
//用于加载item布局
protected LayoutInflater mInflater;
private Context mContext;
protected List<String> mDatas;
/**
* 因为RecyclerView没有提供Item的点击事件,所以这里我们自己定义一个接口
* 来实现点击事件
*/
public interface OnItemClickListener{
void onItemClick(View view,int position);
void onItemLongClick(View view,int position);
}
private OnItemClickListener mOnItemClickListener;
public void setmOnItemClickListener(OnItemClickListener onItemClickListener){
this.mOnItemClickListener=onItemClickListener;
}
/** -------------------------------------------------------------------------- **/
public SimpleAdapter(Context context,List<String> datas) {
this.mContext=context;
this.mDatas=datas;
mInflater=LayoutInflater.from(context);
}
/**
* 在以往的BaseAdapter中会在getView()中去进行创建ViewHolder和对应的View进行
* 赋值,而在此adapter中将这个过程分为了两步,由这两个方法完成
* (可以看出Google开始强制开发者使用ViewHolder模式了)
*/
/**
* 创建ViewHolder
* @param viewGroup
* @param i
* @return
*/
@Override
public MyViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view=mInflater.inflate(R.layout.item_single_textview,viewGroup,false);
MyViewHolder viewHolder=new MyViewHolder(view);
return viewHolder;
}
/**
* 绑定ViewHolder
* @param holder
* @param pos
*/
@Override
public void onBindViewHolder(final MyViewHolder holder, final int pos) {
holder.tv.setText(mDatas.get(pos));
setUpItemEvent(holder);
}
/**
* android studio 快速提取方法 Ctrl + Alt + M
* @param holder
*/
protected void setUpItemEvent(final MyViewHolder holder) {
//为每个Item设置点击事件,实现点击方法的回调
if (mOnItemClickListener!=null){
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int layoutPosition = holder.getLayoutPosition();
mOnItemClickListener.onItemClick(holder.itemView,layoutPosition);
}
});
//longclick
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
int layoutPosition = holder.getLayoutPosition();
mOnItemClickListener.onItemLongClick(holder.itemView, layoutPosition);
/**return false; false后面长按过后会有onItemClick效果出现,所以这里设置true
可以解决这个bug**/
return true;
}
});
}
}
@Override
public int getItemCount() {
return mDatas.size();
}
public void addData(int pos){
mDatas.add(pos,"Insert One");
// notifyDataSetChanged();不是调用这个这里要注意
// notifyItemChanged(pos);这里有很多方法,比如这个就是改变值得更新方法
/**
* notifyItemInserted(pos)不会刷新View,所以会存在添加过后的pos都是一样的问题
*
* 为了得到正确的pos,我们调用holder.getLayoutPosition();来获取Item
* 在布局中的pos就可以得到正确的pos了
*
* 在点击事件中调用了该方法
*/
notifyItemInserted(pos);
}
public void deleteData(int pos){
mDatas.remove(pos);
notifyItemRemoved(pos);
}
class MyViewHolder extends RecyclerView.ViewHolder {
//将item中的控件在这里面进行初始化
TextView tv;
public MyViewHolder(View itemView) {
super(itemView);
tv= (TextView) itemView.findViewById(R.id.id_tv);
}
}
}
接下来是瀑布流布局的实现
StaggeredActivity.java
package cn.bigniu.recyclerviewdemo;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
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 java.util.ArrayList;
import java.util.List;
public class StaggeredActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private List<String> mDatas;
private StaggeredAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化datas
initDatas();
//初始化View
initViews();
mAdapter = new StaggeredAdapter(this, mDatas);
mRecyclerView.setAdapter(mAdapter);
//瀑布流的布局显示
mRecyclerView.setLayoutManager(
new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));
mAdapter.setmOnItemClickListener(new SimpleAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
}
@Override
public void onItemLongClick(View view, int position) {
mAdapter.deleteData(position);
}
});
/*mRecyclerView.addItemDecoration(
new DividerItemDecoration(this,DividerItemDecoration.VERTICAL_LIST));*/
}
private void initViews() {
mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerView);
}
private void initDatas() {
mDatas = new ArrayList<String>();
for (int i = 'A'; i <= 'z'; i++) {
mDatas.add("" + (char) i);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
return super.onOptionsItemSelected(item);
}
}
StaggeredAdapter.java
package cn.bigniu.recyclerviewdemo;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
/**
* 为了减少重新写一次接口,我们直接继承SimpleAdapter
*/
public class StaggeredAdapter extends SimpleAdapter {
//用于加载item布局
/*private LayoutInflater mInflater;
private Context mContext;
private List<String> mDatas;*/
//设置一个随机变量来改变瀑布流布局的高度
private List<Integer> mHeights;
public StaggeredAdapter(Context context, List<String> datas) {
super(context,datas);
/*this.mContext = context;
this.mDatas = datas;
mInflater = LayoutInflater.from(context);*/
mHeights = new ArrayList<Integer>();
for (int i = 0; i < mDatas.size(); i++) {
mHeights.add((int) (100 + Math.random() * 300));
}
}
/*@Override
public StaggeredAdapter.MyViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = mInflater.inflate(R.layout.item_single_textview, viewGroup, false);
MyViewHolder viewHolder = new MyViewHolder(view);
return viewHolder;
}*/
@Override
public void onBindViewHolder(MyViewHolder holder, int pos) {
//itemView就是StaggeredAdapter.MyViewHolder中的view
//设置item的高度
ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
lp.height=mHeights.get(pos);
holder.itemView.setLayoutParams(lp);
holder.tv.setText(mDatas.get(pos));
setUpItemEvent(holder);
}
/*@Override
public int getItemCount() {
return mDatas.size();
}*/
/*class MyViewHolder extends RecyclerView.ViewHolder {
//将item中的控件在这里面进行初始化
TextView tv;
public MyViewHolder(View itemView) {
super(itemView);
tv = (TextView) itemView.findViewById(R.id.id_tv);
}
}*/
}
主布局界面
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"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/id_recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
Item子布局
为了方便和减少布局中出现其他的布局不美观等问题,我们在子布局中设置layout_margin属性来进行分隔
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_margin="3dp"
android:background="@drawable/item_bg"
android:layout_height="72dp">
<TextView
android:id="@+id/id_tv"
android:layout_width="72dp"
android:layout_height="match_parent"
android:gravity="center"/>
</FrameLayout>
Menu布局
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
<!-- ifRoom表示如果Actionbar上有空间,就显示这个menu;
withText表示显示的时候如果空间足够,会显示menu的title。 -->
<item android:id="@+id/action_add"
android:title="Add"
android:orderInCategory="100"
android:icon="@mipmap/ic_menu_add"
app:showAsAction="ifRoom" />
<item android:id="@+id/action_delete"
android:title="Delete"
android:orderInCategory="100"
android:icon="@mipmap/ic_menu_delete"
app:showAsAction="ifRoom" />
<item android:id="@+id/action_listview"
android:title="ListView"
android:orderInCategory="100"
app:showAsAction="never" />
<item android:id="@+id/action_gridview"
android:title="GridView"
android:orderInCategory="100"
app:showAsAction="never" />
<item android:id="@+id/action_hor_gridview"
android:title="HorizontalGridView"
android:orderInCategory="100"
app:showAsAction="never" />
<item android:id="@+id/action_staggered"
android:title="StaggeredGridView"
android:orderInCategory="100"
app:showAsAction="never" />
<item android:id="@+id/action_settings"
android:title="@string/action_settings"
android:orderInCategory="100"
app:showAsAction="never" />
</menu>
其他相关文件
style.xml
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<!-- <item name="android:listDivider">@drawable/divider_02</item>-->
</style>
</resources>
divider_02.xml(自定义分隔线)
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size android:height="4dp"></size>
<!-- 设置渐变的效果 -->
<!-- linear 线性 -->
<!-- 不同的模拟器会加载不同的values,所以要在自己模拟器版本加载的values下添加这个
属性,不然不会有读取的效果-->
<gradient android:startColor="#ffff0000"
android:centerColor="#ff00ff00"
android:endColor="#ff0000ff"
android:type="linear"/>
</shape>
selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@color/state_pressed"></item>
<item android:drawable="@color/state_normal"></item>
</selector>
colors
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="state_pressed">#ffff0000</color>
<color name="state_normal">#44ff00ff</color>
</resources>
DividerItemDecoration.java下载地址