【问题标题】:How to prevent ListView from updating while item is long pressed?长按项目时如何防止 ListView 更新?
【发布时间】:2010-08-22 21:17:05
【问题描述】:

我有一个由某些服务发送意图更新的 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;
        }
    }
}

【问题讨论】:

    标签: android listview


    【解决方案1】:

    抓住长按并防止数据集被更新。覆盖列表视图的 onlongpress 方法。我会在一分钟内发布代码

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

    【讨论】:

    • 我找到了部分基于您的回答的解决方案 :) 谢谢。
    猜你喜欢
    • 1970-01-01
    • 2017-12-15
    • 2019-10-12
    • 1970-01-01
    • 2013-02-23
    • 2019-06-20
    • 2012-04-08
    • 1970-01-01
    • 2019-04-12
    相关资源
    最近更新 更多