Cómo puede mostrar un AdView en cada n-ésima posición en un listView

Tengo el código abajo que trabaja excepto que oculta siempre al menos un artículo verdadero en el listview porque el anuncio aparece en esa posición.

Ejemplo del problema: Tengo una lista de 4 veces, y el adView está mostrando en la posición 3. en el listview que puedo ver solamente 3 veces y el AdView, el 4to artículo no consigue exhibido

He jugado alrededor con el aumento del tamaño del adaptador cada vez que devuelvo un anuncio, pero no funcionó muy bien.

¿Algunas ideas?

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; } } 

Hay más de una manera de lograr esto. La mejor manera es confiar en la capacidad del listView para reciclar múltiples tipos de elementos.

En su adaptador,

  1. getViewTypeCount () – devuelve la información de cuántos tipos de filas tiene en la listaVer
  2. getItemViewType (int position) devuelve información sobre el tipo de disposición que debe usar en función de la posición. Ahí es donde debe ir su lógica de determinar los objetos listView.

Hay un buen tutorial sobre cómo utilizar diferentes tipos de elementos en una lista aquí : Específicamente, consulte "Diseños de diferentes elementos de lista".

Después de eso, necesita conversiones aritméticas menores para sus índices, de forma que pueda asignar la posición al lugar correcto en su estructura de datos (o, puede combinar su estructura de datos para incluir datos de anuncios y datos de elementos).

Básicamente, en lugar de usar items.size () necesitas usar items.size () + Math.floor (items.size () / NTH_ITEM) y cuando consigues la posición, si es una posición del anuncio (posición% NTH_ITEM == 0) utilice una conversión simple como Math.floor (position / NTH_ITEM) para extraer de la estructura de datos del anuncio y de manera similar para la estructura de su elemento.

Usted debe confiar en el patrón del sostenedor del ListView para reutilizar sus diversos tipos de la opinión del artículo, como en el tutorial arriba.

Diferentes enfoques, sólo para la noción es utilizar algo como envoltorios de elementos que combinan el origen de datos en uno y permite diferenciar entre elementos mediante una propiedad de tipo, como un enum o un "adaptador de fusión" que fusiona dos adaptadores específicos (esto podría tienen una mejor modularidad si va a incluir estos tipos de vista en listas diferentes).

Déjame saber si necesitas ayuda para implementar partes específicas de esto en tu caso de uso.

La respuesta de Ben Max es más limpia. Se recomienda utilizar tipos de vista al tratar con diferentes tipos de vista.

Esta es una buena manera de hacerlo.

Cree un contenedor para sus diferentes tipos de datos:

 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; } } 

Ahora vienen algunos de los cambios a su adaptador:

Supongamos que usted consigue inicializar su adaptador en el constructor

  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)); } } 

A continuación, algunos cambios más en su adaptador:

 @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; } 

Ahora para su getView …. Usted verá esto es más agradable porque usted puede controlar cómo sus opiniones son infladas

 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; } 

Usted notará que envolviendo sus datos como este le da un gran control sobre cómo / donde su elemento se muestra simplemente manipulando la lista en lugar de hacer cualquier lógica extraña dentro de su getView (); también hace que sea sencillo dejar que infle diseños de acuerdo al tipo y los llene fácilmente. ¡Espero que esto ayude! PS i escribió una entrada de blog sobre este tema antes también: http://qtcstation.com/2012/04/a-limitation-with-the-viewholder-pattern-on-listview-adapters/

Me gustaría ir de una manera diferente, en lugar de añadir el diseño del anuncio dinámicamente. Suponiendo que su diseño (que se accede a través del parámetro de View row de su método getView() ) se personaliza, simplemente agregue un LinearLayout en el que se utilizará para el AdView .

Como no desea que sea visible en todas las filas, marque su visibilidad de forma predeterminada, pero al definirla de esa manera le permitirá controlar su diseño y definir cómo debe mostrarse.

Suponiendo que este es su archivo de diseño:

 <LinearLayout ...> <!-- Put here the AdView layout --> <LinearLayout android:id="@+id/adViewLL" ... android:visibility="gone" /> <!-- Add whatever else you need in your default layout --> ... </LinearLayout> 

Ahora simplemente cambie su método getView() para establecer la visibilidad VISIBLE cuando lo necesite y coloque allí la View para su 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; } 

Me gustaría añadir a la respuesta de nKn mi siguiente experiencia:

  1. Encapsular la vista de anuncio con ViewSwitcher
  2. Muestre un mensaje donde el anuncio va, algo como: "un mensaje de nuestros patrocinadores encantadores …"
  3. Cuando la devolución de llamada Ad te golpea (onAdLoaded), haz un holder.switcher.setDisplayedChild(1); // if 1 is where your AdView is. holder.switcher.setDisplayedChild(1); // if 1 is where your AdView is.
  4. Tenga una bandera donde pueda inhabilitar los anuncios, así que siempre haga si (showAd && adsEnabled) {}, nunca se sabe cuando es posible que deba inhabilitar anuncios, si tiene una API que intenta recuperar ese valor.
  5. # 4 también se puede usar para una cláusula else: else {holder.switcher.setDisplayedChild(0);//your generic message}
  6. Disponga de un "AdController" en el que determine la frecuencia (cada cual ## de los elementos que desea insertar un anuncio). y haga que su lista pregunte if (YourAdController.isAd(position) && adsEnabled) { do the add thing }

Esto es un poco un error lógico.

Aquí está una explicación de lo que está pasando.

Pasando por su descripción, cada 8x posición es un anuncio

¿Por qué ir a ensuciar con las vistas o el mantenimiento de múltiples diseños

En su conjunto de datos (es decir, la lista que está pasando al adaptador) sólo tiene que agregar un elemento que indique un elemento de anuncio en cada posición 8x

Por lo tanto, si es una versión pro no hay entrada de artículo de anuncio en la lista

Por último, en su getview

 if(ad item) populate adView else populate regularItemView 

Espero que simplifique

Tengo el mismo problema en una de las aplicaciones en las que trabajé. aquí está el enfoque que trabajó conmigo.

  • En primer lugar, debe crear una clase que contenga los detalles de su anuncio.

    public class AdUnitDetails {cadena privada 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; } 

    }

  • A continuación, crea un Sparsearray que contiene anuncios con sus posiciones

     SparseArray<AdView> mAdViewsMap = new SparseArray<AdView>(); 
  • A continuación, debe modificar su adaptador para recibir un arraylist de objetos y, a continuación, agregar los anuncios en sus posiciones correspondientes al llenar esta lista. ejemplo (artículo, artículo, artículo, addetalles, artículo, artículo, etc.).

  • Luego, en su adaptador. agregue los métodos siguientes:

     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); } 
  • Luego, en su método getView() , agregue lo siguiente

      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; 
  • su método 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); } 

    }

Podría ser demasiado tarde, pero aquí es cómo he resuelto el mío. Convertido la posición actual de int a cadena (opcional) y luego cada vista de tiempo se infla, compruebe si la posición contiene (3 || 6 || 9) para que cada 3ª disposición visible muestre un banner publicitario. espero que era útil publicar código si es necesario 🙂 oh y || significa "o" si alguien se está preguntando

aquí está el código 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); 

// si no se muestran sus anuncios de una tercera posición //} eres bienvenido 🙂

  • Lista personalizada con dos botones en cada fila
  • Dos ListView de lado a lado
  • Android: listview item width fill_parent no funciona
  • Ancho y color del borde del elemento ListView de Android
  • Tratando de coger un clic en android ListView item: android: descendantFocusability = "blocksDescendants" no funciona
  • ¿Ocultar la vista de pie en ListView?
  • Cómo eliminar el color seleccionado en arrastrar sobre listview
  • ListView inside SwipeRefreshLayout inside Gaveta (Layout): no bloquea la dirección de desplazamiento
  • Seleccione sólo un botón de radio a la vez en la vista de lista personalizada, android
  • Lista de Android Ver Arrastrar y soltar ordenar
  • Androide. RadioButtons en un ListView
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.