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
SeekBaractivo e inactivo .Al marcar un
SeekBaractivo , proporcione la posición actual (progreso). Junto a, publicar elRunnableque actualizará esteSeekBarAl marcar un
SeekBarinactivo , simplemente elimine las devoluciones de llamada deRunnableyRunnableun 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?