studio metodo example como colocar campo busqueda buscar buscador android listview android-recyclerview seekbar

metodo - searchview android example listview



ListView que recicla interruptores posición de la barra de búsqueda (1)

Esbozaré una de las mejores formas de abordar esto (en mi opinión, por supuesto) al tiempo que respeto ListView''s capacidad de reciclar de ListView''s .

Pero primero, esto tiene que ir :

@Override public int getViewTypeCount() { return getCount(); } @Override public int getItemViewType(int position) { return position; }

Solución:

Subclase SeekBar y déjelo manejar todas las actualizaciones:

  • Defina dos métodos que marcarán a este SeekBar activo e inactivo .

  • Al marcar un SeekBar activo , proporcione la posición actual (progreso). Junto a, publicar el Runnable que actualizará este SeekBar

  • Al marcar un SeekBar inactivo , simplemente elimine las devoluciones de llamada de Runnable y Runnable un día

Dentro de su Adapter , el único estado que necesita mantener es realizar un seguimiento de la canción que se está reproduciendo actualmente. Puede hacer esto ya sea rastreando la posición tal como la ve su ListView , o manteniendo el ID de la pista que se está reproduciendo actualmente (esto, por supuesto, solo funcionará si su modelo usa ID).

Algo como esto:

// Define `setActiveAtPosition(int position)` and `setInactive()` // in your custom SeekBar if (Globals.isPlaying && Globals.pos == position) { // Define `setActiveAtPosition(int position)` in your custom SeekBar holder.seekbar.setActiveAtPosition(Globals.mp.getCurrentPosition()); holder.seekbar.setVisibility(View.VISIBLE); } else { holder.seekbar.setInactiveForNow(); holder.seekbar.setVisibility(View.GONE); }

Código solicitado:

Implementación de clase Seekbar personalizada:

public class SelfUpdatingSeekbar extends SeekBar implements SeekBar.OnSeekBarChangeListener { private boolean mActive = false; private Runnable mUpdateTimeProgressBar = new Runnable() { @Override public void run() { if (Globals.isPlaying) { setProgress(Globals.mp.getCurrentPosition()); postDelayed(this, 100L); } } }; public SelfUpdatingSeekbar(Context context, AttributeSet attrs) { super(context, attrs); setOnSeekBarChangeListener(this); } public void setActive() { if (!mActive) { mActive = true; removeCallbacks(mUpdateTimeProgressBar); setProgress(Globals.mp.getCurrentPosition()); setVisibility(View.VISIBLE); postDelayed(mUpdateTimeProgressBar, 100L); } } public void setInactive() { if (mActive) { mActive = false; removeCallbacks(mUpdateTimeProgressBar); setVisibility(View.INVISIBLE); } } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override public void onStartTrackingTouch(SeekBar seekBar) { removeCallbacks(mUpdateTimeProgressBar); } @Override public void onStopTrackingTouch(SeekBar seekBar) { removeCallbacks(mUpdateTimeProgressBar); Globals.mp.seekTo(getProgress()); postDelayed(mUpdateTimeProgressBar, 500); } }

En getView(...) su adaptador:

if (Globals.isPlaying && Globals.pos == position) { holder.seekbar.setActive(); } else { holder.seekbar.setInactive(); }

No hace falta decir que necesitará usar esta implementación personalizada en su diseño xml:

<com.your.package.SelfUpdatingSeekbar .... .... />

Tengo un problema extraño. Tengo un ListView personalizado con BaseAdapter . En mi diseño de fila de ListView , tengo pocos TextView s, Buttons y SeekBar . Todo funciona muy bien, no hay problemas con nada excepto con el reciclaje.

Qué sucede: todos los SeekBar están ocultos, excepto uno que está visible. SeekBar es visible cuando se SeekBar MediaPlayer en la fila. Esa parte está funcionando bien también.

Pero, cuando el usuario se desplaza hacia arriba o hacia abajo, y la fila con SeekBar visible está fuera de la vista, se recicla, y SeekBar se recicla y se actualiza incluso si no está visible y esa fila no se está reproduciendo (mp). Y cuando los usuarios se desplazan hacia atrás para regresar a la vista que se está reproduciendo, SeekBar está visible, pero no se actualiza y su posición es 0. En lugar de eso, se está actualizando SeekBar azar, pero no está visible (lo hice cuando todos los SeekBar están visibles Sé que eso sucede)

Por supuesto que podría haber hecho la solución más idiota e inhabilitar el reciclaje de ListView, pero esto hace que la experiencia del usuario sea realmente mala y podría hacer que la aplicación se quede sin memoria, y el uso de LargeHeap es lamentable. Entonces los siguientes métodos están fuera de cuestión.

@Override public int getViewTypeCount() { return getCount(); } @Override public int getItemViewType(int position) { return position; }

Mi pregunta: ¿hay alguna solución obvia para esto? ¿Cómo evito que una sola fila sea reciclada? No publicaré el código hasta que sea realmente necesario, el código es demasiado grande. En su lugar, solo publicaré partes importantes relacionadas con el problema:

@Override public View getView(final int position, View convertView, ViewGroup parent) { View row = convertView; holder = null; if (row == null) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); row = inflater.inflate(R.layout.item, parent, false); holder = new Ids(row); row.setTag(holder); } else { holder = (Ids) row.getTag(); } rowItemClass = (ListViewRow) getItem(position); if (Globals.isPlaying && Globals.pos == position) { holder.seekbar.setVisibility(View.VISIBLE); } else { holder.seekbar.setVisibility(View.GONE); } holder.seekbar.setTag(position); final Ids finalHolder = holder; ... OnClickListener{.... Globals.mp.start(); finalHolder.seekbar.setProgress(0); finalHolder.seekbar.setMax(Globals.mp.getDuration()); .. updateTimeProgressBar = new Runnable() { @Override public void run() { if (Globals.isPlaying) { finalHolder.seekbar.setProgress(Globals.mp.getCurrentPosition()); int currentPosition = Globals.mp.getCurrentPosition(); handler.postDelayed(this, 100); } } }; handler.postDelayed(updateTimeProgressBar, 100); finalHolder.seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { @Override public void onStopTrackingTouch(SeekBar seekBar) { handler.removeCallbacks(updateTimeProgressBar); Globals.mp.seekTo(finalHolder.seekbar.getProgress()); int currentPosition = Globals.mp.getCurrentPosition(); handler.postDelayed(updateTimeProgressBar, 500); } @Override public void onStartTrackingTouch(SeekBar seekBar) { handler.removeCallbacks(updateTimeProgressBar); } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // Intentionally left empty } }); }

y eso es. ¿Por qué está pasando esto? ¿Hay alguna manera de desactivar el reciclaje por una fila? ¿Sería una mala idea actualizar todas las SeekBar en ListView ya que solo se reproducirá 1 mp? ¿Qué tan malo es eso para el rendimiento?