先看一下效果,随便从网上找的数据,首先看一下效果 ,随便从网上找的数据 经过简单配置可实现三种不同的配置 很简单
第一种 水平List
第二种 垂直List
第三种 GridVIew 显示
4 点击每个Item 后跳转的页面
(一).前言:
话说RecyclerView已经面市很久,也在很多应用中得到广泛的使用,在整个开发者圈子里面也拥有很不错的口碑,那说明RecyclerView拥有比ListView,GridView之类控件有很多的优点,例如:数据绑定,Item View创建,View的回收以及重用等机制。那么今天开始我们来重点学习一下(二).RecyclerView基本介绍:
通过使用RecyclerView控件,我们可以在APP中创建带有Material Design风格的复杂列表。RecyclerView控件和ListView的原理有很多相似的地方,都是维护少量的View来进行显示大量的数据,不过RecyclerView控件比ListView更加高级并且更加灵活。当我们的数据因为用户事件或者网络事件发生改变的时候也能很好的进行显示。和ListView不同的是,RecyclerView不用在负责Item的显示相关的功能,在这边所有有关布局,绘制,数据绑定等都被分拆成不同的类进行管理,下面我这边会一个个的进行讲解。同时RecyclerView控件提供了以下两种方法来进行简化和处理大数量集合:
为了使用RecyclerView控件,我们需要创建一个Adapter和一个LayoutManager:
Adapter:继承自RecyclerView.Adapetr类,主要用来将数据和布局item进行绑定。
LayoutManager:布局管理器,设置每一项view在RecyclerView中的位置布局以及控件item view的显
示或者隐藏.当View重用或者回收的时候,LayoutManger都会向Adapter来请求新的数据来进行替换原来数据的内容。这种回收重用的机制可以提供性能,避免创建很多的view或者是频繁的调用findViewById方法。这种机制和ListView还是很相似的。
RecyclerView提供了三种内置的LayoutManager:
- LinearLayoutManager:线性布局,横向或者纵向滑动列表
- GridLayoutManager:表格布局
- StaggeredGridLayoutManager:流式布局,例如瀑布流效果
当然除了上面的三种内部布局之外,我们还可以继承RecyclerView.LayoutManager来实现一个自定义的LayoutManager。
Animations(动画)效果:
RecyclerView对于Item的添加和删除是默认开启动画的。我们当然也可以通过RecyclerView.ItemAnimator类定制动画,然后通过RecyclerView.setItemAnimator()方法来进行使用。
(三) 实现 RecyclerView:
<?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:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:layout_alignParentTop="true" android:id="@+id/recycler_view1" android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollbars="none" /> <LinearLayout android:layout_alignParentBottom="true" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:layout_weight="1" android:layout_width="0dp" android:layout_height="wrap_content" android:text="水平List" android:id="@+id/button" /> <Button android:layout_weight="1" android:layout_width="0dp" android:layout_height="wrap_content" android:text="垂直List" android:id="@+id/button1" /> <Button android:layout_weight="1" android:layout_width="0dp" android:layout_height="wrap_content" android:text="GridViewList" android:id="@+id/button2" /> </LinearLayout> </RelativeLayout>2 创建adapter SpeedHourAdapter 如下
SpeedHourAdapter
/** * Created by dhb on 2016/12/13. */ public class SpeedHourAdapter extends RecyclerView.Adapter<SpeedHourHolder> { private List<GoodsEntity> goodsEntityList; private LayoutInflater mInflater; private Context mContext=null; View view; public SpeedHourAdapter(Context context) { this.mContext=context; mInflater = LayoutInflater.from(context); } public void setList(List<GoodsEntity> list) { this.goodsEntityList = list; notifyDataSetChanged(); } public OnItemClickListener mOnItemClickListener; public interface OnItemClickListener { void onItemClick(View view, int position); } public void setOnItemClickListener(OnItemClickListener mOnItemClickLitener) { this.mOnItemClickListener = mOnItemClickLitener; } @Override public SpeedHourHolder onCreateViewHolder(ViewGroup parent, int viewType) { view = mInflater.inflate(R.layout.item_speedhour_layout, parent, false); SpeedHourHolder holder = new SpeedHourHolder(view); return holder; } @Override public void onBindViewHolder(final SpeedHourHolder holder, final int position) { GoodsEntity goodsEntity= goodsEntityList.get(position); if (goodsEntity != null) { holder.speedImage.setScaleType(ImageView.ScaleType.FIT_XY); Glide.with(mContext).load(goodsEntityList.get(position).getPic()).error(R.drawable.welfare_default_icon).into(holder.speedImage); holder.speedName.setText(goodsEntityList.get(position).getGoodsName()); holder.speedPrice.setText("¥"+ goodsEntityList.get(position).getPrice()); } holder.speedView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (mOnItemClickListener!=null){ mOnItemClickListener.onItemClick(holder.speedView,position); } } }); } @Override public int getItemCount() { return goodsEntityList.size(); } } class SpeedHourHolder extends RecyclerView.ViewHolder { LinearLayout speedView= (LinearLayout) itemView.findViewById(R.id.speed_view); ImageView speedImage=(ImageView)itemView.findViewById(R.id.speed_image); TextView speedName=(TextView)itemView.findViewById(R.id.speed_name); TextView speedPrice=(TextView)itemView.findViewById(R.id.speed_price); public SpeedHourHolder(View itemView) { super(itemView); itemView.setTag(this); } }
3 创建 实体类GoodsEntity
/** * Created by dhb on 2016/12/14. */ public class GoodsEntity { public String id; public String price; public String pic; public String getPrice() { return price; } public void setPrice(String price) { this.price = price; } public String url; private String goodsName; public String getGoodsName() { return goodsName; } public void setGoodsName(String goodsName) { this.goodsName = goodsName; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getPic() { return pic; } public void setPic(String pic) { this.pic = pic; } }3穿建主activityMainActivity 如下
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private Button bt1,bt2,bt3; RecyclerView recyclerView; private SpeedHourAdapter speedHourAdapter=null; private SpeedHourEntity entity=null; //List<SpeedHourEntity.TopicBean.ItemsBean.ListBean> listBeen; private List<GoodsEntity> goodList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // SpeedHourView mv = new SpeedHourView(this); setContentView(R.layout.activity_main); // goodList=new ArrayList<>(); /* GoodsEntity goods1=new GoodsEntity(); goods1.setPic("https://img.alicdn.com/imgextra/i1/2465542730/TB2BqGygFXXXXaGXXXXXXXXXXXX_!!2465542730.jpg"); goods1.setUrl("https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-13758825248.80.2fAZyt&id=523787709290"); goods1.setPrice("80"); goods1.setGoodsName("腰鼓舞扇子舞"); goodList.add(goods1); GoodsEntity goods2=new GoodsEntity(); goods2.setPic("https://img.alicdn.com/imgextra/i3/2465542730/TB2xg8huXXXXXbPXXXXXXXXXXXX_!!2465542730.jpg"); goods2.setUrl("https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-13758825248.44.2fAZyt&id=536652066479"); goods2.setGoodsName("民族舞蹈演出"); goods2.setPrice("50"); goodList.add(goods2); GoodsEntity goods3=new GoodsEntity(); goods3.setPic("https://img.alicdn.com/imgextra/i3/2465542730/TB26ZHCgFXXXXXbXXXXXXXXXXXX_!!2465542730.jpg"); goods3.setUrl("https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-13758825248.35.2fAZyt&id=523830222737"); goods3.setGoodsName("主持礼服"); goods3.setPrice("80"); goodList.add(goods3); GoodsEntity goods4=new GoodsEntity(); goods4.setPic("https://gd3.alicdn.com/imgextra/i4/2/TB1AmVlGFXXXXaCXFXXXXXXXXXX_!!2-item_pic.png"); goods4.setUrl("https://item.taobao.com/item.htm?spm=a230r.7195193.1997079397.8.M86mSV&id=44662242725&abbucket=14"); goods4.setGoodsName("舞龙舞狮服"); goods4.setPrice("68.00 - 70.00"); goodList.add(goods4); GoodsEntity goods5=new GoodsEntity(); goods5.setPic("https://gd1.alicdn.com/imgextra/i2/0/TB1_VL9GXXXXXbrXVXXXXXXXXXX_!!0-item_pic.jpg_400x400.jpg"); goods5.setUrl("https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-13758825246.47.uvxE6S&id=523169033768"); goods5.setGoodsName("圣诞表演服圣诞老人"); goods5.setPrice("45.00 - 58.00"); goodList.add(goods5); GoodsEntity goods6=new GoodsEntity(); goods6.setPic("https://gd1.alicdn.com/imgextra/i3/0/TB130xJIXXXXXbdXFXXXXXXXXXX_!!0-item_pic.jpg_400x400.jpg"); goods6.setUrl("https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-13758825246.56.uvxE6S&id=520485740068"); goods6.setGoodsName("傣族舞蹈服装团体"); goods6.setPrice("75.00 - 78.00"); goodList.add(goods6); GoodsEntity goods7=new GoodsEntity(); goods7.setPic("https://img.alicdn.com/imgextra/i4/2465542730/TB2pey9pXXXXXXlXFXXXXXXXXXX_!!2465542730.jpg"); goods7.setUrl(" https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-13758825246.14.uvxE6S&id=531994901741"); goods7.setGoodsName("六一儿童节表演"); goods7.setPrice("35.00 - 42.00"); goodList.add(goods7); GoodsEntity goods8=new GoodsEntity(); goods8.setPic("https://gd3.alicdn.com/imgextra/i2/2/T1Yze2FQ0bXXXXXXXX_!!2-item_pic.png_400x400.jpg"); goods8.setUrl(" https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-13758825246.20.fDvY7b&id=520218493024"); goods8.setGoodsName("纱裙舞蹈服公主裙"); goods8.setPrice("65.00 - 68.00"); goodList.add(goods8); GoodsEntity goods9=new GoodsEntity(); goods9.setPic("https://gd4.alicdn.com/imgextra/i3/2465542730/TB2h2fwXjm2.eBjSZFtXXX56VXa_!!2465542730.png_400x400.jpg"); goods9.setUrl(" https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-13758825249.14.zlv0Js&id=522646513230"); goods9.setGoodsName("演出舞蹈鞋子黑色"); goods9.setPrice("13.00"); goodList.add(goods9); */ init(); /* String strInf=JsonUtils.toJson(goodList); String b="gd";*/ } @Override public void onClick(View v) { switch (v.getId()){ case R.id.button: LinearLayoutManager hList = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);//水平 recyclerView.setLayoutManager(hList);//水平list*/ break; case R.id.button1: LinearLayoutManager vList = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);//垂直 recyclerView.setLayoutManager(vList); break; case R.id.button2: GridLayoutManager mGridViewLayoutManger = new GridLayoutManager(this, 2); recyclerView.setLayoutManager(mGridViewLayoutManger);//gridView显示*/ break; default: GridLayoutManager mGridViewLayoutManger1 = new GridLayoutManager(this, 3); recyclerView.setLayoutManager(mGridViewLayoutManger1);//gridView显示 break; } } private void init() { initData(); initView(); initAdapter(); } private void initData() { String data =""; try { data =AssertsFileUtils.readFileFromAssets(this,"speenhour1.txt"); } catch (IOException e) { e.printStackTrace(); } goodList= GsonUtils.fromJson(data, new TypeToken<List<GoodsEntity>>() { }); } private void initView() { bt1=(Button )this.findViewById(R.id.button); bt2=(Button )this.findViewById(R.id.button1); bt3=(Button )this.findViewById(R.id.button2); bt3.setOnClickListener(this); bt1.setOnClickListener(this); bt2.setOnClickListener(this); recyclerView= (RecyclerView)findViewById(R.id.recycler_view1); LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);//初始化显示 recyclerView.setLayoutManager(linearLayoutManager); /* GridLayoutManager mGridViewLayoutManger1 = new GridLayoutManager(this, 3); recyclerView.setLayoutManager(mGridViewLayoutManger1);*/ } private void initAdapter() { speedHourAdapter=new SpeedHourAdapter(this); recyclerView.setAdapter(speedHourAdapter); if(goodList.size()>0){ speedHourAdapter.setList(goodList); } speedHourAdapter.setOnItemClickListener(new SpeedHourAdapter.OnItemClickListener() { @Override public void onItemClick(View view, int position) { Intent intent =new Intent(); intent.putExtra("url",goodList.get(position).getUrl()); intent.setClass(MainActivity.this, ActivityWeb.class); startActivity(intent); } }); } private long touchTime = 0; private long waitTime = 2000; @Override public void onBackPressed() { // TODO Auto-generated method stub long currentTime = System.currentTimeMillis(); if ((currentTime - touchTime) >= waitTime) { ToastUtility.showToast("再按一次退出"); touchTime = currentTime; } else { finish(); } } }4 创建点击每个Item布局 item_speedhour_layout.xml 如下
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:ptr="http://schemas.android.com/apk/res-auto" android:id="@+id/speed_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:padding="10dp" android:gravity="center"> <ImageView android:id="@+id/speed_image" android:layout_width="85dp" android:layout_height="85dp" android:scaleType="fitXY" /> <TextView android:id="@+id/speed_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:text="儿童服" android:maxLines="1"/> <TextView android:id="@+id/speed_price" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:text="¥50" android:maxLength="6" android:maxLines="1"/> </LinearLayout>5 点击每个item 跳转的activityActivityWeb 如下
public class ActivityWeb extends AppCompatActivity { private WebView webView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_activity_web); Intent intent =getIntent(); String url=intent.getStringExtra("url"); webView = (WebView) findViewById(R.id.webView); WebSettings settings = webView.getSettings(); settings.setJavaScriptEnabled(true); settings.setUseWideViewPort(true);//设定支持viewport settings.setJavaScriptEnabled(true);//允许JS执行 settings.setBuiltInZoomControls(true); //WebView加载web资源 webView.setWebViewClient(new WebViewClient()); webView.loadUrl(url); //覆盖WebView默认使用第三方或系统默认浏览器打开网页的行为,使网页用WebView打开 /*webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { // TODO Auto-generated method stub //返回值是true的时候控制去WebView打开,为false调用系统浏览器或第三方浏览器 view.loadUrl(url); return true; } });*/ } }6对应的布局activity_activity_web 如下
<?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: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"> <WebView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/webView" /> </RelativeLayout>数据我已经转化成jeson数据保存在 speenhour1.txt 中了,方便大家测试下面用道的工具类有GsonUtils,AssertsFileUtils,ToastUtility
public class GsonUtils { private static Gson gson = null; static{ gson = new Gson(); } private GsonUtils(){ throw new UnsupportedOperationException("cannot install this class"); } /** * Object -> JsonString * @param t * @return */ public static <T> String toJson(T t) { return gson.toJson(t); } /** *JsonString -> 指定类型的object * @param jsonString * @param clazz * @return */ public static <T> T fromJson(String jsonString, Class<T> clazz) { return gson.fromJson(jsonString, clazz); } /** * jsonString -> 指定类型的object * @param jsonString * @param typeToken * @return */ public static <T> T fromJson(String jsonString,TypeToken<T> typeToken) { return gson.fromJson(jsonString, typeToken.getType()); } }package yhkj.transition.recyclerviewtest; import android.content.Context; import android.content.res.AssetManager; import android.text.TextUtils; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.List; /** * Created by duanhongbo on 2016/12/13. */ public class AssertsFileUtils { private AssertsFileUtils( ){ } /** * 读取asserts目录下的文件 * @param fileName eg:"updatelog.txt" * @return 对应文件的内容 * * */ public static String readFileFromAssets(Context context, String fileName) throws IOException, IllegalArgumentException { if (null == context || TextUtils.isEmpty(fileName)){ throw new IllegalArgumentException( "bad arguments!" ); } AssetManager assetManager = context.getAssets(); InputStream input = assetManager.open(fileName); ByteArrayOutputStream output = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int length = 0; while ((length = input.read(buffer)) != -1) { output.write(buffer, 0, length); } output.close(); input.close(); return output.toString(); } /** * 列出Asserts文件夹下的所有文件 * @return asserts目录下的文件名列表 * * */ public static List<String> getAssertsFiles( Context context ) throws IllegalArgumentException{ if( null == context ){ throw new IllegalArgumentException( "bad arguments!" ); } AssetManager assetManager = context.getAssets(); String[] files = null; try { files = assetManager.list(""); } catch (IOException e) { e.printStackTrace( ); } return ( null == files )?null: Arrays.asList(files); } }package yhkj.transition.recyclerviewtest; import android.content.Context; import android.widget.Toast; /** * Toast工具类 * * */ public class ToastUtility { private static Context ctx; public static void init(Context context) { if(null == ctx){ ctx = context; } } /** * 构造函数 */ private ToastUtility() { // TODO Auto-generated constructor stub } private static Toast toast; public static void showToast(CharSequence message) { if (null == toast) { toast = Toast.makeText(ctx, message, Toast.LENGTH_SHORT); }else{ toast.setText(message); } toast.show(); } public static void showToast(int resId) { showToast(ctx.getResources().getText(resId)); } // public void showToast(String message, int gravity) { // Toast toast = Toast.makeText(ctx, message, Toast.LENGTH_SHORT); // toast.setGravity(gravity, 0, 0); // toast.show(); // } // // // public void showToast(String message, float horizontalMargin, float verticalMargin) { // Toast toast = Toast.makeText(ctx, message, Toast.LENGTH_SHORT); // toast.setMargin(horizontalMargin, verticalMargin); // toast.show(); // } }需要注意的是 数据我已经保存到 speenhour1.txt中 要放到assets目录下 ,在主activity中读取就行了,数据如下[ { "goodsName": "腰鼓舞扇子舞", "pic": "https://img.alicdn.com/imgextra/i1/2465542730/TB2BqGygFXXXXaGXXXXXXXXXXXX_!!2465542730.jpg", "price": "80", "url": "https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-13758825248.80.2fAZyt&id=523787709290" }, { "goodsName": "民族舞蹈演出", "pic": "https://img.alicdn.com/imgextra/i3/2465542730/TB2xg8huXXXXXbPXXXXXXXXXXXX_!!2465542730.jpg", "price": "50", "url": "https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-13758825248.44.2fAZyt&id=536652066479" }, { "goodsName": "主持礼服", "pic": "https://img.alicdn.com/imgextra/i3/2465542730/TB26ZHCgFXXXXXbXXXXXXXXXXXX_!!2465542730.jpg", "price": "80", "url": "https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-13758825248.35.2fAZyt&id=523830222737" }, { "goodsName": "舞龙舞狮服", "pic": "https://gd3.alicdn.com/imgextra/i4/2/TB1AmVlGFXXXXaCXFXXXXXXXXXX_!!2-item_pic.png", "price": "68.00 - 70.00", "url": "https://item.taobao.com/item.htm?spm=a230r.7195193.1997079397.8.M86mSV&id=44662242725&abbucket=14" }, { "goodsName": "圣诞表演服圣诞老人", "pic": "https://gd1.alicdn.com/imgextra/i2/0/TB1_VL9GXXXXXbrXVXXXXXXXXXX_!!0-item_pic.jpg_400x400.jpg", "price": "45.00 - 58.00", "url": "https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-13758825246.47.uvxE6S&id=523169033768" }, { "goodsName": "傣族舞蹈服装团体", "pic": "https://gd1.alicdn.com/imgextra/i3/0/TB130xJIXXXXXbdXFXXXXXXXXXX_!!0-item_pic.jpg_400x400.jpg", "price": "75.00 - 78.00", "url": "https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-13758825246.56.uvxE6S&id=520485740068" }, { "goodsName": "六一儿童节表演", "pic": "https://img.alicdn.com/imgextra/i4/2465542730/TB2pey9pXXXXXXlXFXXXXXXXXXX_!!2465542730.jpg", "price": "35.00 - 42.00", "url": " https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-13758825246.14.uvxE6S&id=531994901741" }, { "goodsName": "纱裙舞蹈服公主裙", "pic": "https://gd3.alicdn.com/imgextra/i2/2/T1Yze2FQ0bXXXXXXXX_!!2-item_pic.png_400x400.jpg", "price": "65.00 - 68.00", "url": " https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-13758825246.20.fDvY7b&id=520218493024" }, { "goodsName": "演出舞蹈鞋子黑色", "pic": "https://gd4.alicdn.com/imgextra/i3/2465542730/TB2h2fwXjm2.eBjSZFtXXX56VXa_!!2465542730.png_400x400.jpg", "price": "13.00", "url": " https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-13758825249.14.zlv0Js&id=522646513230" } ]放到txt中,方面大家测试今天先写写到这里