我有下面的代码,除了它总是隐藏列表视图中的至少一个真实项目,因为广告显示在该位置。
问题示例:我有4次列表,adView显示在列表视图的第3位我只能看到3次和AdView,第4项没有得到显示
我每次返回广告时都会增加适配器的大小,但效果并不好。
有什么想法吗?
public View getView(final int position, View row, ViewGroup parent) {
MyHolder holder = null;
boolean showAd = proVersion == false && (position % 8 == k);
if (showAd) {
AdView adView = adList.get(position);
if (adView == null) {
AdView adViewNew = new AdView((Activity) context, AdSize.BANNER, context.getResources().getString(
R.string.adId));
adViewNew.loadAd(Utils.getAdRequest("gps", lat, lng, keywords));
adList.add(position, adViewNew);
return adViewNew;
} else {
return adView;
}
} else if (row == null || row instanceof AdView) {
LayoutInflater inflater = ((SherlockActivity) context).getLayoutInflater();
row = inflater.inflate(viewResourceId, parent, false);
holder = new MyHolder();
holder.textName = (TextView) row.findViewById(R.id.name);
row.setTag(holder);
} else {
holder = (MyHolder) row.getTag();
}
holder.textName.setText(items.get(position).getName());
// more code
return row;
}
@Override
public int getCount() {
if (items != null) {
return items.size();
} else {
return 0;
}
}
答案 0 :(得分:6)
实现这一目标的方法不止一种。最好的方法是依靠listView的能力来回收多种项目类型。
在你的适配器中,
有一个关于如何使用different item types in a list here的好教程: 具体来说,请查看“不同列表项”布局。
之后,您需要对索引进行少量算术转换,以便将位置映射到数据结构中的正确位置(或者,您可以合并数据结构以包含广告数据和项目数据)。
基本上,您需要使用items.size()+ Math.floor(items.size()/ NTH_ITEM)而不是使用items.size(),当您获得该位置时,如果它是广告位置(位置%) NTH_ITEM == 0)使用像Math.floor(position / NTH_ITEM)这样的简单转换从广告数据结构中提取,并以类似的方式提取项目的结构。
您应该依赖ListView的holder模式来重用您的不同项视图类型,就像上面的教程一样。
不同的方法,仅用于概念,包括使用类似于将数据源合并为一个的项包装器,并通过使用类型属性(如枚举)或合并两个特定适配器的“合并适配器”来区分项目(如果要将这些视图类型包含在不同的列表中,这可能具有更好的模块性。)
如果您在使用案例中需要任何帮助来实现特定部分,请告诉我。
答案 1 :(得分:3)
Ben Max的回答更清晰。 建议在处理不同类型的视图时使用视图类型。
这是一个很好的方法。
为您的不同数据类型创建一个包装器:
private class ItemWrapper {
public static final int TYPE_NORMAL = 0;
public static final int TYPE_AD = 1;
public static final int TYPE_COUNT = 2;
public ListObject item;
public AdObject adItem;
public int type;
public ItemWrapper(ListObject item) {
this.type = TYPE_NORMAL;
this.item = item
}
public ItemWrapper(AdObject adItem) {
this.type = TYPE_AD;
this.adItem = adItem;
}
}
现在对适配器进行一些更改:
假设您在构造函数中初始化适配器
public class MyAdapter extends BaseAdapter{
ArrayList<ItemWrapper> mWrappedItems = new ArrayList<ItemWrapper>();
public void MyAdapter(List<ListObject> items,AdItem adItem){
for(ListObject item:items){
mWrappedItems.add(new ItemWrapper(item));
}
//you can insert your ad item wherever you want!
mWrappedItems.add(2,new ItemWrapper(adItem));
}
}
然后对适配器进行一些更改:
@Override
public ItemWrapper getItem(int position) {
return mWrappedItems == null ? null : mWrappedItems.get(position);
}
@Override
public int getItemViewType(int position) {
return getItem(position).type;
}
@Override
public int getViewTypeCount() {
//tells the adapter how many different view types it will need to recycle
return ItemWrapper.TYPE_COUNT;
}
现在为你的getView .... 你会发现这更好,因为你可以控制你的观点被夸大的方式
public View getView(final int position, View row, ViewGroup parent) {
final ItemWrapper item = getItem(position);
final int type = item.type;
if (row == null) {
if (type == ItemWrapper.TYPE_NORMAL) {
//inflate your normal view layouts
} else if (type == ItemWrapper.TYPE_AD) {
//inflate your ad layout
}
}
//now you can easily populate your views based on the type
if (type == ItemWrapper.TYPE_NORMAL) {
//get your item data
final ListObject data = item.item;
//populate as you would normally
} else if (type == ItemWrapper.TYPE_AD) {
final AdItem adItem = item.adItem;
//populate your ad as needed
}
return row;
}
您会注意到,通过操作列表而不是在getView()中执行任何奇怪的逻辑,您可以很好地控制项目的显示方式/位置。它还使您可以轻松地根据类型扩展布局并轻松填充它们。 我希望这有帮助! P.S我之前也写了一篇关于这个主题的博客文章: http://qtcstation.com/2012/04/a-limitation-with-the-viewholder-pattern-on-listview-adapters/
答案 2 :(得分:1)
我会采用不同的方式,而不是动态添加广告布局。假设您的布局(通过View row
方法的getView()
参数访问)是自定义的,只需在其中添加LinearLayout
,该AdView
将用于<LinearLayout
...>
<!-- Put here the AdView layout -->
<LinearLayout
android:id="@+id/adViewLL"
...
android:visibility="gone" />
<!-- Add whatever else you need in your default layout -->
...
</LinearLayout>
。< / p>
由于您不希望它在所有行上都可见,因此默认情况下标记其可见性已经消失,但以这种方式定义它将允许您控制布局并定义它应如何显示。
假设这是你的布局文件:
getView()
现在只需更改您的VISIBLE
方法,即可在{14}}时将展示次数设置为View
,并为AdView
添加public View getView(final int position, View row, ViewGroup parent) {
MyHolder holder = null;
boolean showAd = proVersion == false && (position % 8 == k);
if (row == null) {
LayoutInflater inflater = ((SherlockActivity) context).getLayoutInflater();
row = inflater.inflate(viewResourceId, parent, false);
holder = new MyHolder();
holder.textName = (TextView) row.findViewById(R.id.name);
row.setTag(holder);
if (showAd) {
LinearLayout myAd = (LinearLayout) row.findViewByid(R.id.adViewLL);
myAd.setVisibility(View.VISIBLE);
AdView adViewNew = new AdView((Activity) context, AdSize.BANNER, context.getResources().getString(R.string.adId));
...
myAd.addView(adViewNew);
}
} else {
holder = (MyHolder) row.getTag();
}
holder.textName.setText(items.get(position).getName());
// more code
return row;
}
。
{{1}}
答案 3 :(得分:0)
我会在nKn的回答中添加以下经验:
holder.switcher.setDisplayedChild(1); // if 1 is where your AdView is.
else {holder.switcher.setDisplayedChild(0);//your generic message}
if (YourAdController.isAd(position) && adsEnabled) { do the add thing }
答案 4 :(得分:0)
这是一个逻辑错误。
以下是对发生的事情的解释。
根据您的说明,每8次展位都是广告
为什么继续搞乱视图或维护多个布局
在您的数据集中(即您传递给适配器的列表),只需在每个 8x 位置添加一个表示广告项的项目
因此,如果是专业版,则列表中没有广告项条目
最后,在你的getview中
if(ad item)
populate adView
else
populate regularItemView
希望它简化
答案 5 :(得分:0)
我在其中一个应用程序上遇到了同样的问题。这是与我合作的方法。
首先,您需要创建一个包含广告详细信息的类。
公共类AdUnitDetails { private String mUnitId; private int mIndex;
public AdUnitDetails(String mUnitId,int mIndex) {
super();
this.mUnitId = mUnitId;
this.mIndex = mIndex;
}
public String getUnitId() {
return mUnitId;
}
public void setUnitId(String mUnitId) {
this.mUnitId = mUnitId;
}
public int getIndex() {
return mIndex;
}
public void setIndex(int mIndex) {
this.mIndex = mIndex;
}
}
然后,您创建一个包含其位置
的广告的SparsearraySparseArray<AdView> mAdViewsMap = new SparseArray<AdView>();
然后,您需要修改适配器以接收对象的arraylist,然后在填写此列表时将广告添加到相应的位置。示例(项目,项目,项目,addetails,项目,项目等)。
然后,在您的适配器中。添加以下方法:
private static final int TYPE_ITEM= 0;
private static final int TYPE_AD = 1;
private static final int TYPES_COUNT = TYPE_AD + 1;
@Override
public int getViewTypeCount() {
return TYPES_COUNT;
}
@Override
public int getItemViewType(int position) {
if (mItems.get(position) instanceof YourItemClass)
return TYPE_ITEM;
else if (mItems.get(position) instanceof AdUnitDetails)
return TYPE_AD;
return super.getItemViewType(position);
}
然后,在您的getView()
方法中,添加以下内容
View view = convertView;
if (mItems.get(position) instanceof YourItemClass) {
// Handle your listview item view
} else if (mItems.get(position) instanceof AdUnitDetails) {
return getAdView(position);
}
return view;
您的getAdView()
方法
private AdView getAdView(final int position) {
if (mAdViewsMap.get(position) == null) {
AdSize adSize = getAdSize(AdSize.BANNER);
AdView mAdView = new AdView(mContext, adSize, ((AdUnitDetails) mItems.get(position)).getUnitId());
mAdView.loadAd(new AdRequest());
mAdViewsMap.put(position, mAdView);
return mAdView;
} else {
return mAdViewsMap.get(position);
}
}
答案 6 :(得分:0)
可能为时已晚,但这就是我如何解决我的问题。 将当前位置从int转换为string(可选) 然后每次视图膨胀时检查位置是否包含(3 || 6 || 9),因为每个第3个可见布局都显示广告横幅。希望它有用,如果需要,将发布代码:) 哦和||意味着&#34;或&#34;如果有人想知道
答案 7 :(得分:0)
这里是代码Ashish Kumar Gupta
RelativeLayout rl = (RelativeLayout) convertView.findViewById(R.id.adviewlayout); //putting the advertisement banner inside a relativelayout/linearlayout if you want. so that you can make it visibile whenever you want.
String pos = String.valueOf(position); // converting listview item position from int to string//
if (pos.endsWith("3")||pos.endsWith("6")||pos.endsWith("9")) {
// every fourth position will show an advertisement banner inside a listview. here is the proof (0,1,2,advertisement,4,5,advertisement,7,8,advertisement,10,11,12,advertisement,14,15,advertisement,17,18,advertisement,20). did not put advertisements in 0 position cuz its rude to put advertisements in like the first layout in my POV//
rl.setVisibility(View.VISIBLE);
}
else
{
rl.setVisibility(View.GONE);
//如果不是第3个位置的广告将不会显示// } 欢迎你:)