首页 > 代码库 > Android商城开发系列(七)—— 使用RecyclerView展示首页数据
Android商城开发系列(七)—— 使用RecyclerView展示首页数据
前面我们讲到了使用OkHttp请求网络和FastJson解析数据了,接下来我们就开始把获取到的数据通过数据适配器展示在页面上了。Adapter是用来帮助填充数据的中间桥梁,简单点说就是:将各种数据以合适的形式显示到view上,提供给用户看!
商城首页的数据是使用RecyclerView进行展示的,下面我们来讲讲如何将获取到的数据通过RecyclerView展示。
首先看一下HomeFragment的布局代码,代码如下:
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent"> 6 7 <!--搜索框布局--> 8 <include 9 android:id="@+id/titlebar" 10 layout="@layout/titlebar"/> 11 12 <!--展示数据的RecyclerView--> 13 <android.support.v7.widget.RecyclerView 14 android:id="@+id/rv_home" 15 android:layout_width="match_parent" 16 android:layout_height="match_parent" 17 android:layout_below="@id/titlebar" /> 18 19 <!--回到顶部图片按钮--> 20 <ImageButton 21 android:id="@+id/ib_top" 22 android:layout_width="40dp" 23 android:layout_height="40dp" 24 android:layout_alignParentBottom="true" 25 android:layout_alignParentRight="true" 26 android:layout_marginBottom="20dp" 27 android:layout_marginRight="20dp" 28 android:background="@mipmap/ic_launcher" 29 android:visibility="gone" /> 30 31 32 </RelativeLayout>
布局代码很简单,整体是一个RelativeLayout布局,里面有一个RecyclerView,用于展示数据,接下来我们看一下HomeFragment的代码:
1 package com.nyl.shoppingmall.home.fragment; 2 3 import android.support.v7.widget.GridLayoutManager; 4 import android.support.v7.widget.RecyclerView; 5 import android.util.Log; 6 import android.view.View; 7 import android.widget.ImageView; 8 import android.widget.TextView; 9 import android.widget.Toast; 10 11 import com.alibaba.fastjson.JSON; 12 import com.nyl.shoppingmall.R; 13 import com.nyl.shoppingmall.base.BaseFragment; 14 import com.nyl.shoppingmall.home.adapter.HomeFragmentAdapter; 15 import com.nyl.shoppingmall.home.bean.ResultBeanData; 16 import com.nyl.shoppingmall.utils.Constants; 17 import com.zhy.http.okhttp.OkHttpUtils; 18 import com.zhy.http.okhttp.callback.StringCallback; 19 20 import okhttp3.Call; 21 22 /** 23 * 首页Fragment 24 */ 25 public class HomeFragment extends BaseFragment implements View.OnClickListener { 26 27 private final static String TAG = HomeFragment.class.getSimpleName(); 28 29 private TextView tv_search_home; 30 private TextView tv_message_home; 31 private RecyclerView rv_home; 32 private ImageView ib_top; 33 private HomeFragmentAdapter adapter; 34 //返回的数据 35 private ResultBeanData.ResultBean resultBean; 36 37 @Override 38 public View initView() { 39 Log.e(TAG,"主页面的Fragment的UI被初始化了"); 40 View view = View.inflate(mContext,R.layout.fragment_home,null); 41 //初始化布局控件 42 tv_search_home = (TextView) view.findViewById(R.id.tv_search_home); 43 tv_message_home = (TextView) view.findViewById(R.id.tv_message_home); 44 rv_home = (RecyclerView) view.findViewById(R.id.rv_home); 45 ib_top = (ImageView) view.findViewById(R.id.ib_top); 46 47 //设置点击事件 48 ib_top.setOnClickListener(this); 49 tv_search_home.setOnClickListener(this); 50 tv_message_home.setOnClickListener(this); 51 return view; 52 } 53 54 55 @Override 56 public void initData() { 57 super.initData(); 58 Log.e(TAG,"主页面的Fragment的数据被初始化了"); 59 60 //联网请求首页数据 61 getDataFromNet(); 62 } 63 64 private void getDataFromNet() { 65 // String url = Constants.HOME_URL; 66 OkHttpUtils 67 .get() 68 .url(Constants.HOME_URL) 69 .build() 70 .execute(new StringCallback() 71 { 72 73 /** 74 * 请求失败的时候回调 75 * @param call 76 * @param e 77 * @param id 78 */ 79 @Override 80 public void one rror(Call call, Exception e, int id) { 81 82 Log.e(TAG,"首页请求失败=="+e.getMessage()); 83 } 84 85 /** 86 * 当联网成功的时候回调 87 * @param response 请求成功数据 88 * @param id 89 */ 90 @Override 91 public void onResponse(String response, int id) { 92 93 Log.e(TAG,"首页请求成功=="+response); 94 //解析数据 95 processData(response); 96 } 97 }); 98 } 99 100 /** 101 * 解析数据 102 * @param json 103 */ 104 private void processData(String json) { 105 //使用FastJson去解析数据,将Json字符串转换成一个ResultBeanData对象 106 ResultBeanData resultBeanData = http://www.mamicode.com/JSON.parseObject(json,ResultBeanData.class); 107 resultBean = resultBeanData.getResult(); 108 109 if (resultBean != null){ 110 //有数据就设置适配器 111 adapter = new HomeFragmentAdapter(mContext,resultBean); 112 rv_home.setAdapter(adapter); 113 114 GridLayoutManager manager = new GridLayoutManager(mContext,1); 115 //设置跨度大小监听 116 manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { 117 @Override 118 public int getSpanSize(int position) { 119 if (position <= 3){ 120 //隐藏 121 ib_top.setVisibility(View.GONE); 122 }else { 123 //显示 124 ib_top.setVisibility(View.VISIBLE); 125 } 126 //只能返回1 127 return 1; 128 } 129 }); 130 //设置布局管理者 131 rv_home.setLayoutManager(manager); 132 }else { 133 //没有数据 134 135 } 136 137 Log.e(TAG,"解析成功=="+resultBean.getHot_info().get(0).getName()); 138 } 139 140 @Override 141 public void onClick(View view) { 142 switch (view.getId()){ 143 case R.id.ib_top: //置顶的监听 144 rv_home.scrollToPosition(0); 145 break; 146 case R.id.tv_search_home: //搜索的监听 147 Toast.makeText(mContext,"搜索",Toast.LENGTH_SHORT).show(); 148 break; 149 case R.id.tv_message_home: //消息监听 150 Toast.makeText(mContext,"进入消息中心",Toast.LENGTH_SHORT).show(); 151 break; 152 } 153 } 154 }
HomeFragmet的代码也很简单,首先是初始化视图,然后联网调用接口获取数据,通过FastJson解析数据,然后将数据传入到HomeFragmentAdapter进行展示,接下来我们看一下HomeFragmentAdapter,这个适配器是展示数据的具体实现:
HomeFragmentAdapter类代码如下所示:
1 package com.nyl.shoppingmall.home.adapter; 2 3 import android.content.Context; 4 import android.content.Intent; 5 import android.os.Handler; 6 import android.os.Message; 7 import android.support.v4.view.PagerAdapter; 8 import android.support.v4.view.ViewPager; 9 import android.support.v7.widget.LinearLayoutManager; 10 import android.support.v7.widget.RecyclerView; 11 import android.view.LayoutInflater; 12 import android.view.View; 13 import android.view.ViewGroup; 14 import android.widget.AdapterView; 15 import android.widget.GridView; 16 import android.widget.ImageView; 17 import android.widget.TextView; 18 import android.widget.Toast; 19 20 import com.bumptech.glide.Glide; 21 import com.nyl.shoppingmall.R; 22 import com.nyl.shoppingmall.app.activity.GoodsInfoActivity; 23 import com.nyl.shoppingmall.home.bean.ResultBeanData; 24 import com.nyl.shoppingmall.utils.Constants; 25 import com.youth.banner.Banner; 26 import com.youth.banner.BannerConfig; 27 import com.youth.banner.Transformer; 28 import com.youth.banner.listener.OnBannerClickListener; 29 import com.youth.banner.listener.OnLoadImageListener; 30 import com.zhy.magicviewpager.transformer.ScaleInTransformer; 31 32 import java.text.SimpleDateFormat; 33 import java.util.ArrayList; 34 import java.util.Date; 35 import java.util.List; 36 37 /** 38 * 首页适配器 39 */ 40 41 public class HomeFragmentAdapter extends RecyclerView.Adapter{ 42 43 /** 44 * 广告幅类型 45 */ 46 public static final int BANNER = 0; 47 48 /** 49 * 频道类型 50 */ 51 public static final int CHANNEL = 1; 52 53 /** 54 * 活动类型 55 */ 56 public static final int ACT = 2; 57 58 /** 59 * 秒杀类型 60 */ 61 public static final int SECKILL = 3; 62 63 /** 64 * 推荐类型 65 */ 66 public static final int RECOMMEND = 4; 67 68 /** 69 * 热卖类型 70 */ 71 public static final int HOT = 5; 72 73 /** 74 * 初始化布局 75 */ 76 private LayoutInflater mLayoutInflater; 77 78 /** 79 * 数据 80 */ 81 private ResultBeanData.ResultBean resultBean; 82 83 84 private Context mContext; 85 86 /** 87 * 当前类型 88 */ 89 private int currenType = BANNER; 90 91 public HomeFragmentAdapter(Context mContext, ResultBeanData.ResultBean resultBean) { 92 this.mContext = mContext; 93 this.resultBean = resultBean; 94 mLayoutInflater = LayoutInflater.from(mContext); 95 } 96 97 /** 98 * 根据视图类型创建ViewHolder 99 * @param parent 100 * @param viewType 当前的视图类型 101 * @return RecyclerView.ViewHolder 102 */ 103 @Override 104 public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 105 //广告福 106 if (viewType == BANNER){ 107 //创建BannerViewHolder,Banner里面传布局文件 108 return new BannerViewHolder(mContext,mLayoutInflater.inflate(R.layout.banner_viewpager,null)); 109 //频道 110 }else if (viewType == CHANNEL){ 111 return new ChannelViewHolder(mContext,mLayoutInflater.inflate(R.layout.channel_item,null)); 112 //活动 113 }else if (viewType == ACT){ 114 return new ActViewHolder(mContext,mLayoutInflater.inflate(R.layout.act_item,null)); 115 //秒杀 116 }else if (viewType == SECKILL){ 117 return new SeckillViewHolder(mContext,mLayoutInflater.inflate(R.layout.seckkill_item,null)); 118 //推荐 119 }else if (viewType == RECOMMEND){ 120 return new RecommendViewHolder(mContext,mLayoutInflater.inflate(R.layout.recommend_item,null)); 121 //热卖 122 }else if (viewType == HOT){ 123 return new HotViewHolder(mContext,mLayoutInflater.inflate(R.layout.hot_item,null)); 124 } 125 return null; 126 } 127 128 /** 129 * 绑定数据到ViewHolder 130 * @param holder 131 * @param position 132 */ 133 @Override 134 public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 135 /** 136 * 轮循广告 137 */ 138 if (getItemViewType(position) == BANNER){ 139 BannerViewHolder bannerViewHolder = (BannerViewHolder) holder; 140 bannerViewHolder.setData(resultBean.getBanner_info()); 141 142 } 143 /** 144 * 频道 145 */ 146 else if (getItemViewType(position) == CHANNEL){ 147 ChannelViewHolder channelViewHolder = (ChannelViewHolder) holder; 148 channelViewHolder.setData(resultBean.getChannel_info()); 149 150 } 151 /** 152 * 活动 153 */ 154 else if (getItemViewType(position) == ACT){ 155 ActViewHolder actViewHolder = (ActViewHolder) holder; 156 actViewHolder.setData(resultBean.getAct_info()); 157 158 } 159 /** 160 * 秒杀 161 */ 162 else if (getItemViewType(position) == SECKILL){ 163 SeckillViewHolder seckillViewHolder = (SeckillViewHolder) holder; 164 seckillViewHolder.setData(resultBean.getSeckill_info()); 165 166 } 167 /** 168 * 推荐 169 */ 170 else if (getItemViewType(position) == RECOMMEND){ 171 RecommendViewHolder recommendViewHolder = (RecommendViewHolder) holder; 172 recommendViewHolder.setData(resultBean.getRecommend_info()); 173 174 } 175 /** 176 * 热卖 177 */ 178 else if (getItemViewType(position) == HOT){ 179 HotViewHolder hotViewHolder = (HotViewHolder) holder; 180 hotViewHolder.setData(resultBean.getHot_info()); 181 } 182 } 183 184 /** 185 * 广告幅 186 */ 187 class BannerViewHolder extends RecyclerView.ViewHolder{ 188 189 private Context mContext; 190 private Banner banner; 191 192 public BannerViewHolder(Context mContext, View itemView) { 193 super(itemView); 194 this.mContext = mContext; 195 this.banner = (Banner) itemView.findViewById(R.id.banner); 196 } 197 198 public void setData(List<ResultBeanData.ResultBean.BannerInfoEntity> banner_info) { 199 //得到图片集合地址 200 List<String> imagesUrl = new ArrayList<>(); 201 for (int i = 0;i<banner_info.size();i++){ 202 String imageUrl = banner_info.get(i).getImage(); 203 imagesUrl.add(imageUrl); 204 } 205 //设置循环指示点 206 banner.setBannerStyle(BannerConfig.CIRCLE_INDICATOR); 207 //设置手风琴效果 208 banner.setBannerAnimation(Transformer.Accordion); 209 //设置Banner图片数据 210 banner.setImages(imagesUrl, new onl oadImageListener() { 211 @Override 212 public void onl oadImage(ImageView view, Object url) { 213 //联网请求图片-Glide 214 Glide.with(mContext).load(Constants.BASE_URL_IMAGE + url).into(view); 215 } 216 }); 217 //设置点击事件 218 banner.setOnBannerClickListener(new OnBannerClickListener() { 219 @Override 220 public void OnBannerClick(int position) { 221 Toast.makeText(mContext,"position=="+position,Toast.LENGTH_SHORT).show(); 222 //跳转到商品信息界面 223 startGoodsInfoActivity(); 224 } 225 226 }); 227 } 228 } 229 230 /** 231 * 频道 232 */ 233 class ChannelViewHolder extends RecyclerView.ViewHolder{ 234 235 private Context mContext; 236 private GridView gv_channel; 237 private ChannelAdapter adapter; 238 239 public ChannelViewHolder(Context mContext, View itemView) { 240 super(itemView); 241 this.mContext = mContext; 242 gv_channel = (GridView) itemView.findViewById(R.id.gv_channel); 243 } 244 245 public void setData(List<ResultBeanData.ResultBean.ChannelInfoBean> channel_info) { 246 //得到数据后,就设置GridView的适配器 247 adapter = new ChannelAdapter(mContext,channel_info); 248 gv_channel.setAdapter(adapter); 249 250 //设置item的点击事件 251 gv_channel.setOnItemClickListener(new AdapterView.OnItemClickListener() { 252 @Override 253 public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) { 254 Toast.makeText(mContext,"position"+position,Toast.LENGTH_SHORT).show(); 255 } 256 }); 257 } 258 } 259 260 /** 261 * 活动 262 */ 263 class ActViewHolder extends RecyclerView.ViewHolder{ 264 265 private Context mContext; 266 private ViewPager act_viewpager; 267 268 public ActViewHolder(Context mContext,View itemView) { 269 super(itemView); 270 this.mContext = mContext; 271 act_viewpager = (ViewPager) itemView.findViewById(R.id.act_viewpager); 272 } 273 274 public void setData(final List<ResultBeanData.ResultBean.ActInfoEntity> act_info) { 275 //设置间距 276 act_viewpager.setPageMargin(20); 277 act_viewpager.setOffscreenPageLimit(3);//>=3 278 //setPageTransformer 决定动画效果 279 act_viewpager.setPageTransformer(true, new ScaleInTransformer()); 280 //有数据后,就设置数据适配器 281 act_viewpager.setAdapter(new PagerAdapter() { 282 @Override 283 public int getCount() { 284 return act_info.size(); 285 } 286 287 /** 288 * 289 * @param view 页面 290 * @param object instantiateItem方法返回的值 291 * @return 292 */ 293 @Override 294 public boolean isViewFromObject(View view, Object object) { 295 return view == object; 296 } 297 298 /** 299 * 300 * @param container ViewPager 301 * @param position 对应页面的位置 302 * @return 303 */ 304 @Override 305 public Object instantiateItem(ViewGroup container, final int position) { 306 //实例化ImageView 307 ImageView imageView = new ImageView(mContext); 308 //设置ImageView的拉伸 309 imageView.setScaleType(ImageView.ScaleType.FIT_XY); 310 //根据Glide设置图片 311 Glide.with(mContext).load(Constants.BASE_URL_IMAGE+act_info.get(position).getIcon_url()).into(imageView); 312 //添加到容器中 313 container.addView(imageView); 314 315 //设置点击事件 316 imageView.setOnClickListener(new View.OnClickListener() { 317 @Override 318 public void onClick(View view) { 319 Toast.makeText(mContext,"position=="+position,Toast.LENGTH_SHORT).show(); 320 } 321 }); 322 return imageView; 323 } 324 325 @Override 326 public void destroyItem(ViewGroup container, int position, Object object) { 327 container.removeView((View) object); 328 } 329 }); 330 } 331 } 332 333 /** 334 * 秒杀 335 */ 336 class SeckillViewHolder extends RecyclerView.ViewHolder{ 337 338 private Context mContext; 339 private TextView tv_time_seckill; 340 private TextView tv_more_seckill; 341 private RecyclerView rv_seckill; 342 private SeckillRecycleViewAdapter adapter; 343 344 /** 345 * 相差多少时间-毫秒 346 */ 347 private long dt = 0; 348 //不断循环 349 private Handler handler = new Handler(){ 350 @Override 351 public void handleMessage(Message msg) { 352 super.handleMessage(msg); 353 dt = dt - 1000; 354 //设置具体的时间 355 SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm:ss"); 356 String time = dateFormat.format(new Date(dt)); 357 tv_time_seckill.setText(time); 358 359 handler.removeMessages(0); 360 //发送消息,不断减时间 361 handler.sendEmptyMessageDelayed(0,1000); 362 if (dt <= 0){ 363 //把消息移除 364 handler.removeCallbacksAndMessages(null); 365 } 366 } 367 }; 368 369 public SeckillViewHolder(Context mContext, View itemView) { 370 super(itemView); 371 this.mContext = mContext; 372 //初始化布局控件 373 tv_time_seckill = (TextView) itemView.findViewById(R.id.tv_time_seckill); 374 tv_more_seckill = (TextView) itemView.findViewById(R.id.tv_more_seckill); 375 rv_seckill = (RecyclerView) itemView.findViewById(R.id.rv_seckill); 376 } 377 378 public void setData(ResultBeanData.ResultBean.SeckillInfoEntity seckill_info) { 379 //得到数据后,就是设置数据(TextView和RecyclerView)的数据 380 adapter = new SeckillRecycleViewAdapter(mContext,seckill_info.getList()); 381 rv_seckill.setAdapter(adapter); 382 383 //设置布局管理器 384 rv_seckill.setLayoutManager(new LinearLayoutManager(mContext,LinearLayoutManager.HORIZONTAL,false)); 385 //设置item的点击事件 386 adapter.setOnSeckillRecyclerView(new SeckillRecycleViewAdapter.OnSeckillRecyclerView() { 387 @Override 388 public void onItemClick(int position) { 389 Toast.makeText(mContext,"秒杀"+position,Toast.LENGTH_SHORT).show(); 390 startGoodsInfoActivity(); 391 } 392 }); 393 //秒杀倒计时-毫秒 394 dt = Integer.valueOf(seckill_info.getEnd_time()) - Integer.valueOf(seckill_info.getStart_time()); 395 //进入后1秒钟就去发送这个消息 396 handler.sendEmptyMessageDelayed(0,1000); 397 398 } 399 } 400 401 /** 402 * 推荐 403 */ 404 class RecommendViewHolder extends RecyclerView.ViewHolder{ 405 406 private final Context mContext; 407 private TextView tv_more_recommend; 408 private GridView gv_recommend; 409 private RecommendGridViewAdapter adapter; 410 411 public RecommendViewHolder(final Context mContext, View itemView) { 412 super(itemView); 413 this.mContext = mContext; 414 tv_more_recommend = (TextView) itemView.findViewById(R.id.tv_more_recommend); 415 gv_recommend = (GridView) itemView.findViewById(R.id.gv_recommend); 416 417 //设置点击事件 418 gv_recommend.setOnItemClickListener(new AdapterView.OnItemClickListener() { 419 @Override 420 public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) { 421 Toast.makeText(mContext,"position=="+position,Toast.LENGTH_SHORT).show(); 422 startGoodsInfoActivity(); 423 } 424 }); 425 } 426 427 public void setData(List<ResultBeanData.ResultBean.RecommendInfoBean> recommend_info) { 428 //有数据了之后,就设置适配器 429 adapter = new RecommendGridViewAdapter(mContext,recommend_info); 430 gv_recommend.setAdapter(adapter); 431 432 } 433 } 434 435 /** 436 * 热门 437 */ 438 class HotViewHolder extends RecyclerView.ViewHolder{ 439 440 private final Context mContext; 441 private TextView tv_more_hot; 442 private GridView gv_hot; 443 private HotGridViewAdapter adapter; 444 445 public HotViewHolder(final Context mContext, View itemView) { 446 super(itemView); 447 this.mContext = mContext; 448 tv_more_hot = (TextView) itemView.findViewById(R.id.tv_more_hot); 449 gv_hot = (GridView) itemView.findViewById(R.id.gv_hot); 450 //设置item的点击事件 451 gv_hot.setOnItemClickListener(new AdapterView.OnItemClickListener() { 452 @Override 453 public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) { 454 Toast.makeText(mContext,"position"+position,Toast.LENGTH_SHORT).show(); 455 startGoodsInfoActivity(); 456 } 457 }); 458 } 459 460 public void setData(List<ResultBeanData.ResultBean.HotInfoBean> hot_info) { 461 //有数据后,就设置GridView的适配器 462 adapter = new HotGridViewAdapter(mContext,hot_info); 463 gv_hot.setAdapter(adapter); 464 } 465 } 466 467 468 /** 469 * 启动商品信息列表页面 470 */ 471 private void startGoodsInfoActivity() { 472 Intent intent = new Intent(mContext, GoodsInfoActivity.class); 473 mContext.startActivity(intent); 474 } 475 476 /** 477 * 根据position得到不同的类型 478 * @param position 479 * @return 480 */ 481 @Override 482 public int getItemViewType(int position) { 483 switch (position){ 484 case BANNER: //广告幅 485 currenType = BANNER; 486 break; 487 case CHANNEL: //频道 488 currenType = CHANNEL; 489 break; 490 case ACT: //活动 491 currenType = ACT; 492 break; 493 case SECKILL: //秒杀 494 currenType = SECKILL; 495 break; 496 case RECOMMEND: //推荐 497 currenType = RECOMMEND; 498 break; 499 case HOT: //热卖 500 currenType = HOT; 501 break; 502 } 503 return currenType; 504 } 505 506 /** 507 * 总共有多少个item 508 * @return 509 */ 510 @Override 511 public int getItemCount() { 512 return 6; 513 } 514 515 516 }
HomeFragmentAdapter的代码非常多,但思路是很清晰的,HomeFragmentAdapter是一个多布局item的RecyclerView.Adapter,里面定义了6种不同的item视图类型,在onCreateViewHolder方法中
根据viewType构建出每个item的布局(ViewHolder),然后在onBindViewHolder方法中将数据绑定到不同ViewHolder上。最终效果图如下:
关于使用RecyclerView展示首页数据的内容就介绍这么多。下一篇将具体介绍HomeFragmentAdapter中每一个item的布局实现
Android商城开发系列(七)—— 使用RecyclerView展示首页数据
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。