You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在视频播放器应用的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 18:54:08