如何在视频播放器应用的RecyclerView条目间插入适配网格/列表布局的原生广告
实现方案
下面是基于你现有代码的完整修改步骤,适配列表、网格两种布局的原生广告插入:
1. 定义ViewType与扩展数据模型
首先在BaseVideoAdapter中新增4种条目类型常量,同时给你的BaseModel新增isAd()方法(或新增boolean isAd字段),用来区分普通视频和广告条目:
// 加在BaseVideoAdapter类顶部 private static final int VIEW_TYPE_VIDEO_GRID = 0; private static final int VIEW_TYPE_VIDEO_LIST = 1; private static final int VIEW_TYPE_AD_GRID = 2; private static final int VIEW_TYPE_AD_LIST = 3;
创建广告数据类继承BaseModel:
public class AdModel extends BaseModel { // 可根据需求新增广告相关字段,比如广告标题、封面、跳转链接等 @Override public boolean isAd() { return true; } }
2. 实现广告插入逻辑
新增广告批量插入方法,可在视频列表加载完成后调用,下面示例为每5个视频插入1条广告:
public void insertAdsIntoList() { // 先清空原有广告避免重复插入 ArrayList<BaseModel> videoOnlyList = new ArrayList<>(); for (BaseModel model : arrayVideoList) { if (!model.isAd()) { videoOnlyList.add(model); } } arrayVideoList.clear(); for (int i = 0; i < videoOnlyList.size(); i++) { arrayVideoList.add(videoOnlyList.get(i)); // 每5个视频插入1条广告,跳过最后一条末尾 if ((i + 1) % 5 == 0 && i != videoOnlyList.size() - 1) { arrayVideoList.add(new AdModel()); } } arrayFilterList = arrayVideoList; notifyDataSetChanged(); }
3. 重写getItemViewType
替换原来返回position的错误逻辑,根据条目类型和当前布局返回对应ViewType:
@Override public int getItemViewType(int position) { BaseModel item = arrayFilterList.get(position); boolean isGridMode = Util.VIEW_TYPE.equals("GRID"); if (item.isAd()) { return isGridMode ? VIEW_TYPE_AD_GRID : VIEW_TYPE_AD_LIST; } return isGridMode ? VIEW_TYPE_VIDEO_GRID : VIEW_TYPE_VIDEO_LIST; }
4. 新增广告ViewHolder
先创建两个广告布局文件R.layout.item_ad_grid(网格样式广告)、R.layout.item_ad_list(列表样式广告),然后在Adapter中新增对应ViewHolder:
public class AdGridViewHolder extends RecyclerView.ViewHolder { // 初始化网格广告布局内的控件 public AdGridViewHolder(@NonNull View itemView) { super(itemView); // 比如:adCover = itemView.findViewById(R.id.ad_cover); } } public class AdListViewHolder extends RecyclerView.ViewHolder { // 初始化列表广告布局内的控件 public AdListViewHolder(@NonNull View itemView) { super(itemView); // 比如:adTitle = itemView.findViewById(R.id.ad_title); } }
5. 修改onCreateViewHolder
根据ViewType返回对应ViewHolder:
@NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(activity); switch (viewType) { case VIEW_TYPE_VIDEO_GRID: View gridVideoView = inflater.inflate(R.layout.home_all_video_grid, parent, false); MyClassView gridHolder = new MyClassView(gridVideoView); ViewGroup.LayoutParams params = gridVideoView.getLayoutParams(); if (params != null) { WindowManager wm = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE); int width = wm.getDefaultDisplay().getWidth(); params.height = width / 2; } return gridHolder; case VIEW_TYPE_VIDEO_LIST: View listVideoView = inflater.inflate(R.layout.home_all_video_list, parent, false); return new MyClassViewList(listVideoView); case VIEW_TYPE_AD_GRID: View gridAdView = inflater.inflate(R.layout.item_ad_grid, parent, false); return new AdGridViewHolder(gridAdView); case VIEW_TYPE_AD_LIST: View listAdView = inflater.inflate(R.layout.item_ad_list, parent, false); return new AdListViewHolder(listAdView); default: throw new IllegalArgumentException("未知条目类型"); } }
6. 修改onBindViewHolder
区分广告和普通视频的绑定逻辑,原有视频绑定逻辑不变:
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override public void onBindViewHolder(RecyclerView.ViewHolder holders, int position) { BaseModel item = arrayFilterList.get(position); // 广告绑定逻辑 if (item.isAd()) { if (holders instanceof AdGridViewHolder) { AdGridViewHolder adHolder = (AdGridViewHolder) holders; // 写入网格广告加载逻辑 } else if (holders instanceof AdListViewHolder) { AdListViewHolder adHolder = (AdListViewHolder) holders; // 写入列表广告加载逻辑 } return; } // 原有普通视频绑定逻辑保持不变,直接复用你原来的代码即可 RequestOptions options = new RequestOptions(); File file1 = new File(item.getPath()); if (file1.exists()) { if (Util.VIEW_TYPE.equals("GRID")) { MyClassView holder = (MyClassView) holders; holder.mThumbnail.setClipToOutline(true); holder.mThumbnail.setAdjustViewBounds(true); Glide.with(activity) .load(item.getPath()) .apply(options.centerCrop() .skipMemoryCache(true) .priority(Priority.LOW) .format(DecodeFormat.PREFER_ARGB_8888)) .into(holder.mThumbnail); if (Util.NameField) { holder.mVideoTitle.setVisibility(View.VISIBLE); String fileNameWithOutExt = FilenameUtils.removeExtension(file1.getName()); holder.mVideoTitle.setText(fileNameWithOutExt); } else { holder.mVideoTitle.setText("Video"); } holder.mThumbnail.setOnClickListener(v -> { PlayerActivity playerActivity = new PlayerActivity(); playerActivity.SetList(arrayFilterList, position); Intent in = new Intent(activity, PlayerActivity.class); in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); activity.startActivity(in); }); holder.mMore.setOnClickListener(v -> anInterface.onMoreClick(item, position)); } else { MyClassViewList holder = (MyClassViewList) holders; holder.mThumbnail.setClipToOutline(true); holder.mThumbnail.setAdjustViewBounds(true); Glide.with(activity) .load(item.getPath()) .apply(options.centerCrop() .skipMemoryCache(true) .priority(Priority.LOW) .format(DecodeFormat.PREFER_ARGB_8888)) .into(holder.mThumbnail); if (Util.NameField) { holder.mVideoTitle.setVisibility(View.VISIBLE); String fileNameWithOutExt = FilenameUtils.removeExtension(file1.getName()); holder.mVideoTitle.setText(fileNameWithOutExt); } else { holder.mVideoTitle.setText("Video"); } if (Util.ExtensionField) { holder.mVideoExt.setVisibility(View.VISIBLE); holder.mVideoExt.setText("Type : " + FilenameUtils.getExtension(file1.getName())); } else { holder.mVideoExt.setVisibility(View.GONE); } if (Util.PathField) { holder.mVideoPath.setVisibility(View.VISIBLE); holder.mVideoPath.setText(file1.getParentFile().getPath()); } else { holder.mVideoPath.setVisibility(View.GONE); } if (Util.DateField) { holder.dateCV.setVisibility(View.VISIBLE); String dateString = new SimpleDateFormat("dd LLL yyyy").format(new Date(file1.lastModified())); holder.mVideoDate.setText(dateString); } else { holder.dateCV.setVisibility(View.GONE); } if (Util.LengthField) { holder.mVideoDuration.setVisibility(View.VISIBLE); try { holder.mVideoDuration.setText(Util.generateTime(file1)); } catch (Exception e) { holder.mVideoDuration.setVisibility(View.GONE); } } else { holder.mVideoDuration.setVisibility(View.GONE); } if (Util.SizeField) { holder.mVideoSize.setVisibility(View.VISIBLE); holder.mVideoSize.setText(Util.getSize(file1.length())); } else { holder.mVideoSize.setVisibility(View.GONE); } holder.cardList.setOnClickListener(v -> { Log.e("File:", arrayFilterList.get(position).getPath()); PlayerActivity playerActivity = new PlayerActivity(); playerActivity.SetList(arrayFilterList, position); Intent in = new Intent(activity, PlayerActivity.class); in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); activity.startActivity(in); }); holder.mMore.setOnClickListener(v -> anInterface.onMoreClick(item, position)); } } }
7. 修改过滤逻辑,避免广告被过滤
调整getFilter方法,保证广告不会被搜索过滤掉:
@Override public Filter getFilter() { return new Filter() { @Override protected FilterResults performFiltering(CharSequence charSequence) { String charString = charSequence.toString(); ArrayList<BaseModel> filteredList = new ArrayList<>(); if (charString.isEmpty()) { filteredList.addAll(arrayVideoList); } else { for (BaseModel row : arrayVideoList) { // 广告直接加入结果集 if (row.isAd()) { filteredList.add(row); continue; } if (row.getName().toLowerCase().contains(charString.toLowerCase())) { filteredList.add(row); } } } FilterResults filterResults = new FilterResults(); filterResults.values = filteredList; return filterResults; } @Override protected void publishResults(CharSequence charSequence, FilterResults filterResults) { arrayFilterList = (ArrayList<BaseModel>) filterResults.values; notifyDataSetChanged(); } }; }
8. 网格布局适配,广告占满整行
在你初始化RecyclerView的GridLayoutManager处添加SpanSizeLookup,让广告条目占满所有列:
// 假设你的网格布局是2列 GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 2); gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { int viewType = adapter.getItemViewType(position); // 广告占满整行,普通视频占1列 return viewType == VIEW_TYPE_AD_GRID ? gridLayoutManager.getSpanCount() : 1; } }); recyclerView.setLayoutManager(gridLayoutManager);
内容的提问来源于stack exchange,提问作者Bhagwati Suthar
相关产品推荐
相关产品推荐

