2010-08-22 2 views
0

J'ai un ListView qui est mis à jour par une intention d'envoi de service. Si l'événement de mise à jour arrive alors que j'appuie sur un élément de la ListView, j'ai un comportement bizarre. Le rectangle orange par défaut de l'élément sélectionné disparaît et le texte d'autres éléments devient plus sombre (comme si l'élément était enfoncé).Comment empêcher la mise à jour de ListView lorsque l'élément est enfoncé?

Comment est-ce que je diffère la mise à jour ListView après qu'il ne soit pas "pressé"? Ou plus spécifiquement, quels événements dois-je écouter pour déterminer que ListView n'est plus pressé? (Je peux créer un thread exécuté périodiquement pour mettre à jour quand c'est approprié, mais je pense que c'est excessif). Ou peut-être y at-il une meilleure solution ou solution de contournement.

Voici un exemple de code illustrant le problème. Le service envoie les intentions de mise à jour toutes les 2 secondes. Si j'essaie d'appuyer longuement sur un élément de la liste, j'obtiens le comportement bizarre que j'ai décrit ci-dessus.

L'activité:

package org.me.listviewupdate; 

import android.app.ListActivity; 
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.content.IntentFilter; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Message; 
import android.widget.ArrayAdapter; 

public class MyActivity extends ListActivity { 
    private class MyHandler extends Handler { 
     @Override 
     public void handleMessage(Message msg) { 
      switch (msg.what) { 
       case MSG_UPDATE_DATA: 
        mAdapter.notifyDataSetChanged(); 
        break; 
       default: 
        super.handleMessage(msg); 
        break; 
      } 
     } 
    } 

    private class MyBroadcastReceiver extends BroadcastReceiver { 
     @Override 
     public void onReceive(Context context, Intent intent) { 
      mHandler.sendEmptyMessage(MSG_UPDATE_DATA); 
     } 
    } 

    private static final int MSG_UPDATE_DATA = 0; 

    private String[] mItems = new String[] { "Item1", "Item2", "Item3", "Item4" }; 
    private ArrayAdapter<String> mAdapter; 
    private Handler mHandler; 
    private BroadcastReceiver mBroadcastReceiver; 

    @Override 
    public void onCreate(Bundle icicle) { 
     super.onCreate(icicle); 
     mHandler = new MyHandler(); 
     mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, 
       android.R.id.text1, mItems); 
     setListAdapter(mAdapter); 
     mBroadcastReceiver = new MyBroadcastReceiver(); 
     registerReceiver(mBroadcastReceiver, new IntentFilter(MyService.UPDATE_EVENT)); 
     startService(new Intent(this, MyService.class)); 
    } 

    @Override 
    protected void onDestroy() { 
     unregisterReceiver(mBroadcastReceiver); 
     stopService(new Intent(this, MyService.class)); 
     super.onDestroy(); 
    } 
} 

Le service:

package org.me.listviewupdate; 

import android.app.Service; 
import android.content.Intent; 
import android.os.IBinder; 
import java.util.concurrent.Executors; 
import java.util.concurrent.ScheduledExecutorService; 
import java.util.concurrent.TimeUnit; 

public class MyService extends Service { 
    private class MyUpdateTask implements Runnable { 
     public void run() { 
      sendBroadcast(new Intent(UPDATE_EVENT)); 
     } 
    } 

    public static final String UPDATE_EVENT = 
      "org.me.listviewupdate.intent.event.UPDATED"; 

    private static final int UPDATE_INTERVAL = 2; 

    private ScheduledExecutorService mUpdater; 

    @Override 
    public IBinder onBind(Intent arg0) { 
     return null; 
    } 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     mUpdater = Executors.newSingleThreadScheduledExecutor(); 
    } 

    @Override 
    public void onDestroy() { 
     mUpdater.shutdownNow(); 
     super.onDestroy(); 
    } 

    @Override 
    public void onStart(Intent intent, int startId) { 
     super.onStart(intent, startId); 
     mUpdater.scheduleAtFixedRate(new MyUpdateTask(), UPDATE_INTERVAL, 
       UPDATE_INTERVAL, TimeUnit.SECONDS); 
    } 
} 

Merci.

Ma solution. Eh bien, juste au cas où cela pourrait aider quelqu'un ici est ma solution. Le code ajouté à MyActivity.onCreate():

getListView().setOnTouchListener(new OnTouchListener() { 
    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     boolean isReleased = event.getAction() == MotionEvent.ACTION_UP 
       || event.getAction() == MotionEvent.ACTION_CANCEL; 

     if (mHasPendingUpdate && isReleased) { 
      mHandler.sendEmptyMessage(MSG_UPDATE_DATA); 
     } 
     return false; 
    } 
}); 
getListView().setOnKeyListener(new OnKeyListener() { 
    @Override 
    public boolean onKey(View v, int keyCode, KeyEvent event) { 
     boolean isKeyOfInterest = keyCode == KeyEvent.KEYCODE_DPAD_CENTER 
       || keyCode == KeyEvent.KEYCODE_ENTER; 
     boolean isReleased = event.getAction() == KeyEvent.ACTION_UP; 

     if (mHasPendingUpdate && isKeyOfInterest && isReleased) { 
      mHandler.sendEmptyMessage(MSG_UPDATE_DATA); 
     } 
     return false; 
    } 
}); 

J'ai également ajouté une variable mHasPendingUpdate et modifiée MyHandler:

private class MyHandler extends Handler { 
    @Override 
    public void handleMessage(Message msg) { 
     switch (msg.what) { 
      case MSG_UPDATE_DATA: 
       if (getListView().isPressed()) { 
        mHasPendingUpdate = true; 
       } else { 
        mAdapter.notifyDataSetChanged(); 
        mHasPendingUpdate = false; 
       } 
       break; 
      default: 
       super.handleMessage(msg); 
       break; 
     } 
    } 
} 

Répondre

0

Catch the LongPress et empêcher l'ensemble de données de mise à jour. Remplacer la méthode onlongpress de listview. Je vais poster le code dans une minute

Mise à jour: En fait. Cela peut ne pas fonctionner car il peut être mis à jour pendant que vous appuyez sur, mais avant que la méthode longpress ne soit appelée. Si ce que j'ai suggéré ci-dessus ne fonctionne pas, j'implémenterais onClickListener sur votre ListActivity, j'écouterais tout mouvement, définirais la variable globale empêchant la mise à jour, et retournerais false dans la méthode onMotionEvent() afin que l'élément de liste puisse consommer le clic .

+0

J'ai trouvé une solution basée en partie sur votre réponse :) Merci. – brambury

Questions connexes