AdMob 覆盖 Recyclerview 列表项
AdMob Overlaying Recyclerview List Item
我在 Recycler 列表视图中添加了 Admob 横幅广告,但广告覆盖了列表项。我一直在寻找解决这个问题的方法,我最接近的是
我已经尝试了本文提供的几个答案,但都没有成功。横幅添加始终覆盖列表项。从下图中可以看出,有五款游戏,而第 4 款游戏应该显示在横幅广告下方。
谁能帮我解决这个问题。我在下面放置了我的适配器的代码。
private List<Game> gameList;
private Activity gamesActivity;
private LayoutInflater inflater;
private static final int CONTENT_TYPE = 1;
private static final int AD_TYPE = 0;
private static final int AD_DELTA = 3;
public void notifyDatasetChanged(List<Game> newGamelist) {
gameList.clear();
gameList.addAll(newGamelist);
super.notifyDataSetChanged();
}
class MyViewHolder extends RecyclerView.ViewHolder {
private TextView gameLeagueId;
private TextView gameBowlerId;
private TextView gameSeriesId;
private TextView gameName;
private TextView score;
private TextView strikes;
private TextView spares;
private TextView splits;
private TextView splitConversions;
private TextView openFrames;
private TextView timestamp;
public TextView buttonViewOptions;
public MyViewHolder(View view) {
super(view);
if (!(itemView instanceof AdView)) {
gameLeagueId = view.findViewById( R.id.tvLeagueId );
gameBowlerId = view.findViewById( R.id.tvBowlerId );
gameSeriesId = view.findViewById( R.id.tvSeriesId );
gameName = view.findViewById(R.id.tvGameName);
score = view.findViewById( R.id.tvScore );
strikes = view.findViewById( R.id.tvStrikes );
spares = view.findViewById( R.id.tvSpares );
splits = view.findViewById( R.id.tvSplits );
splitConversions = view.findViewById( R.id.tvSplitConversions );
openFrames = view.findViewById( R.id.tvOpenFrames );
timestamp = view.findViewById( R.id.timestamp );
buttonViewOptions = view.findViewById(R.id.buttonViewOptions);
}
}
}
GamesAdapter(Context context, List<Game> gameList) {
this.context = context;
this.gameList = gameList;
gamesActivity = (Activity) context;
inflater = LayoutInflater.from(context);
}
@Override
public GamesAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
AdView adview;
GamesAdapter.MyViewHolder holder;
if (viewType == AD_TYPE) {
adview = new AdView(gamesActivity);
adview.setAdSize( AdSize.BANNER);
// this is the good adview
adview.setAdUnitId(gamesActivity.getString(R.string.admob_ad_id));
float density = gamesActivity.getResources().getDisplayMetrics().density;
int height = Math.round(AdSize.BANNER.getHeight() * density);
AbsListView.LayoutParams params = new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, height);
adview.setLayoutParams(params);
// dont use below if testing on a device
// follow https://developers.google.com/admob/android/quick-start?hl=en to setup testing device
AdRequest request = new AdRequest.Builder().build();
if (request != null && adview != null) {
adview.loadAd(request);
}
holder = new MyViewHolder(adview);
}else{
View view = inflater.inflate(R.layout.listview_games, parent, false);
holder = new MyViewHolder(view);
}
return holder;
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
if (getItemViewType(position)==CONTENT_TYPE) {
Game game = gameList.get( position );
int id = game.getId();
String leagueId = game.getLeagueId();
String bowlerId = game.getBowlerId();
String seriesId = game.getSeriesId();
String gameNumber = String.valueOf(position+1);
holder.gameLeagueId.setText( game.getLeagueId() );
holder.gameBowlerId.setText( game.getBowlerId() );
holder.gameSeriesId.setText( game.getSeriesId() );
holder.gameName.setText(String.format("Game %s",gameNumber));
holder.score.setText( game.getScore() );
if (game.getStrikes() == "1") {
holder.strikes.setText( String.format( "%s Strike ", game.getStrikes()));
} else holder.strikes.setText( String.format( "%s Strikes", game.getStrikes()));
if (game.getSpares() == "1") {
holder.spares.setText( String.format( "%s Spare ", game.getSpares()));
} else holder.spares.setText( String.format( "%s Spares", game.getSpares()));
if (game.getSplits() == "1") {
holder.splits.setText( String.format( "%s Split ", game.getSplits()));
} else holder.splits.setText( String.format( "%s Splits", game.getSplits()));
if (game.getSplitConversions() == "1") {
holder.splitConversions.setText( String.format( "%s Split Conversion", game.getSplitConversions()));
} else holder.splitConversions.setText( String.format( "%s Split Conversions", game.getSplitConversions()));
if (game.getOpenFrames() == "1") {
holder.openFrames.setText( String.format( "%s Open Frame", game.getOpenFrames()));
} else holder.openFrames.setText( String.format( "%s Open Frames", game.getOpenFrames()));
// Formatting and displaying timestamp
holder.timestamp.setText( formatDate( game.getTimestamp() ) );
holder.buttonViewOptions.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View view) {
//creating a popup menu
PopupMenu popup = new PopupMenu( context, holder.buttonViewOptions );
//inflating menu from xml resource
popup.inflate( R.menu.series_options_menu );
//adding click listener
popup.setOnMenuItemClickListener( new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.profile:
((GamesActivity) context).openDialog( true, gameList.get( position ), leagueId, bowlerId, seriesId, position );
break;
case R.id.delete:
((GamesActivity) context).deleteGame( position );
break;
}
return false;
}
} );
//displaying the popup
popup.show();
}
} );
}
}
@Override
public int getItemCount() {
return gameList.size();
}
//Formatting TimeStamp to 'EEE MMM dd yyyy (HH:mm:ss)'
//Input : 2018-05-23 9:59:01
//Output : Wed May 23 2018 (9:59:01)
private String formatDate(String dateStr) {
try {
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = fmt.parse(dateStr);
SimpleDateFormat fmtOut = new SimpleDateFormat("EEE MMM dd yyyy (HH:mm:ss)");
return fmtOut.format(date);
} catch (ParseException ignored) {
}
return "";
}
@Override
public int getItemViewType(int position) {
if (position > 0 && position % AD_DELTA == 0) {
return AD_TYPE;
}
return CONTENT_TYPE;
}
将对象列表传递给回收器视图时,它期望单个模型(单个对象类型)。在您的情况下,您传递的是 Game 对象。
假设您有一个包含 5 个对象的列表(如您的示例所示)。构建您的支架时,您将用 AD_VIEW 替换第四个对象,而不是为第四个对象构建支架。
解决方案一:
将 AdView 添加到您的布局,其中 visibility=GONE
当您的位置变量满足要求时,将可见性设置为 VISIBLE。
方案二:
创建一个看起来像这样的包装器对象:
public class Wrapper{
public Game game;
public boolean isAd;
}
并在您想要的位置传递一个对象。因此,在示例的情况下,您应该传递 5 个分配了游戏对象的 Wrapper 对象,并在您想要的位置传递第 6 个 Wrapper 对象,它具有 isAd=true 和 game=null。
我在 Recycler 列表视图中添加了 Admob 横幅广告,但广告覆盖了列表项。我一直在寻找解决这个问题的方法,我最接近的是
我已经尝试了本文提供的几个答案,但都没有成功。横幅添加始终覆盖列表项。从下图中可以看出,有五款游戏,而第 4 款游戏应该显示在横幅广告下方。
谁能帮我解决这个问题。我在下面放置了我的适配器的代码。
private List<Game> gameList;
private Activity gamesActivity;
private LayoutInflater inflater;
private static final int CONTENT_TYPE = 1;
private static final int AD_TYPE = 0;
private static final int AD_DELTA = 3;
public void notifyDatasetChanged(List<Game> newGamelist) {
gameList.clear();
gameList.addAll(newGamelist);
super.notifyDataSetChanged();
}
class MyViewHolder extends RecyclerView.ViewHolder {
private TextView gameLeagueId;
private TextView gameBowlerId;
private TextView gameSeriesId;
private TextView gameName;
private TextView score;
private TextView strikes;
private TextView spares;
private TextView splits;
private TextView splitConversions;
private TextView openFrames;
private TextView timestamp;
public TextView buttonViewOptions;
public MyViewHolder(View view) {
super(view);
if (!(itemView instanceof AdView)) {
gameLeagueId = view.findViewById( R.id.tvLeagueId );
gameBowlerId = view.findViewById( R.id.tvBowlerId );
gameSeriesId = view.findViewById( R.id.tvSeriesId );
gameName = view.findViewById(R.id.tvGameName);
score = view.findViewById( R.id.tvScore );
strikes = view.findViewById( R.id.tvStrikes );
spares = view.findViewById( R.id.tvSpares );
splits = view.findViewById( R.id.tvSplits );
splitConversions = view.findViewById( R.id.tvSplitConversions );
openFrames = view.findViewById( R.id.tvOpenFrames );
timestamp = view.findViewById( R.id.timestamp );
buttonViewOptions = view.findViewById(R.id.buttonViewOptions);
}
}
}
GamesAdapter(Context context, List<Game> gameList) {
this.context = context;
this.gameList = gameList;
gamesActivity = (Activity) context;
inflater = LayoutInflater.from(context);
}
@Override
public GamesAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
AdView adview;
GamesAdapter.MyViewHolder holder;
if (viewType == AD_TYPE) {
adview = new AdView(gamesActivity);
adview.setAdSize( AdSize.BANNER);
// this is the good adview
adview.setAdUnitId(gamesActivity.getString(R.string.admob_ad_id));
float density = gamesActivity.getResources().getDisplayMetrics().density;
int height = Math.round(AdSize.BANNER.getHeight() * density);
AbsListView.LayoutParams params = new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, height);
adview.setLayoutParams(params);
// dont use below if testing on a device
// follow https://developers.google.com/admob/android/quick-start?hl=en to setup testing device
AdRequest request = new AdRequest.Builder().build();
if (request != null && adview != null) {
adview.loadAd(request);
}
holder = new MyViewHolder(adview);
}else{
View view = inflater.inflate(R.layout.listview_games, parent, false);
holder = new MyViewHolder(view);
}
return holder;
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
if (getItemViewType(position)==CONTENT_TYPE) {
Game game = gameList.get( position );
int id = game.getId();
String leagueId = game.getLeagueId();
String bowlerId = game.getBowlerId();
String seriesId = game.getSeriesId();
String gameNumber = String.valueOf(position+1);
holder.gameLeagueId.setText( game.getLeagueId() );
holder.gameBowlerId.setText( game.getBowlerId() );
holder.gameSeriesId.setText( game.getSeriesId() );
holder.gameName.setText(String.format("Game %s",gameNumber));
holder.score.setText( game.getScore() );
if (game.getStrikes() == "1") {
holder.strikes.setText( String.format( "%s Strike ", game.getStrikes()));
} else holder.strikes.setText( String.format( "%s Strikes", game.getStrikes()));
if (game.getSpares() == "1") {
holder.spares.setText( String.format( "%s Spare ", game.getSpares()));
} else holder.spares.setText( String.format( "%s Spares", game.getSpares()));
if (game.getSplits() == "1") {
holder.splits.setText( String.format( "%s Split ", game.getSplits()));
} else holder.splits.setText( String.format( "%s Splits", game.getSplits()));
if (game.getSplitConversions() == "1") {
holder.splitConversions.setText( String.format( "%s Split Conversion", game.getSplitConversions()));
} else holder.splitConversions.setText( String.format( "%s Split Conversions", game.getSplitConversions()));
if (game.getOpenFrames() == "1") {
holder.openFrames.setText( String.format( "%s Open Frame", game.getOpenFrames()));
} else holder.openFrames.setText( String.format( "%s Open Frames", game.getOpenFrames()));
// Formatting and displaying timestamp
holder.timestamp.setText( formatDate( game.getTimestamp() ) );
holder.buttonViewOptions.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View view) {
//creating a popup menu
PopupMenu popup = new PopupMenu( context, holder.buttonViewOptions );
//inflating menu from xml resource
popup.inflate( R.menu.series_options_menu );
//adding click listener
popup.setOnMenuItemClickListener( new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.profile:
((GamesActivity) context).openDialog( true, gameList.get( position ), leagueId, bowlerId, seriesId, position );
break;
case R.id.delete:
((GamesActivity) context).deleteGame( position );
break;
}
return false;
}
} );
//displaying the popup
popup.show();
}
} );
}
}
@Override
public int getItemCount() {
return gameList.size();
}
//Formatting TimeStamp to 'EEE MMM dd yyyy (HH:mm:ss)'
//Input : 2018-05-23 9:59:01
//Output : Wed May 23 2018 (9:59:01)
private String formatDate(String dateStr) {
try {
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = fmt.parse(dateStr);
SimpleDateFormat fmtOut = new SimpleDateFormat("EEE MMM dd yyyy (HH:mm:ss)");
return fmtOut.format(date);
} catch (ParseException ignored) {
}
return "";
}
@Override
public int getItemViewType(int position) {
if (position > 0 && position % AD_DELTA == 0) {
return AD_TYPE;
}
return CONTENT_TYPE;
}
将对象列表传递给回收器视图时,它期望单个模型(单个对象类型)。在您的情况下,您传递的是 Game 对象。
假设您有一个包含 5 个对象的列表(如您的示例所示)。构建您的支架时,您将用 AD_VIEW 替换第四个对象,而不是为第四个对象构建支架。
解决方案一: 将 AdView 添加到您的布局,其中 visibility=GONE 当您的位置变量满足要求时,将可见性设置为 VISIBLE。
方案二: 创建一个看起来像这样的包装器对象:
public class Wrapper{
public Game game;
public boolean isAd;
}
并在您想要的位置传递一个对象。因此,在示例的情况下,您应该传递 5 个分配了游戏对象的 Wrapper 对象,并在您想要的位置传递第 6 个 Wrapper 对象,它具有 isAd=true 和 game=null。