长按项目时如何防止ListView更新?

时间:2010-08-22 07:18:31

标签: android listview

我有一个ListView,它由一些服务发送意图更新。如果在我按下ListView中的某个项目时更新事件到达,我会得到一些奇怪的行为。按下的项目中的默认橙色矩形消失,其他一些项目的文本变暗(就像正在按下其项目一样)。

如何在“未按下”后推迟ListView更新?或者更具体地说,我应该监听哪些事件以确定不再按下ListView? (我可以创建一些定期执行的线程,以便在适当的时候进行更新,但我认为这太过分了)。或者可能有更好的解决方案或解决方法。

以下是说明问题的示例代码。服务每2秒发送一次更新意图。如果我尝试长按列表中的某个项目,我会得到上面描述的奇怪行为。

活动:

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

服务:

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

谢谢。

我的解决方案。嗯,以防万一可以帮助这里的人是我的解决方案。代码已添加到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;
    }
});

我还添加了变量mHasPendingUpdate并修改了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;
        }
    }
}

1 个答案:

答案 0 :(得分:0)

捕获longpress并阻止更新数据集。覆盖listview的onlongpress方法。我会在一分钟内发布代码

更新: 其实。这可能不起作用,因为它可以在您按下时但在调用longpress方法之前更新。如果我上面提到的不起作用,我会在ListActivity上实现onClickListener,监听任何运动事件,设置阻止更新的全局变量,并在onMotionEvent()方法中返回false,以便列表项可以消耗点击