Как я могу сделать кнопку более отзывчивой?
Я заметил, что некоторые кнопки не кажутся такими отзывчивыми, какими они могут быть. Это в равной степени относится к моему приложению и к большинству других приложений, которые я пробовал.
Когда я нажимаю кнопку, есть небольшая часть задержки (EDIT: я бы оценил около 20-50 мс), прежде чем кнопка загорится в нажатом состоянии. Некоторым приложениям удалось удалить этот бит задержки, например RealCalc (доступный на рынке), кнопки которого переключаются в нажатое состояние сразу после нажатия на них.
В большинстве случаев это отставание не заметно, но в моем случае, когда кнопки используются в пользовательской цифровой клавиатуре, эта небольшая часть задержки отстает от пользователя. RealCalc чувствует себя намного более отзывчивым и отполированным, потому что это отставание удалено.
Мой вопрос: как удалить эту задержку? Я знаю, что я мог бы просто подкласс, переопределить onTouchEvent и перейти оттуда, но я бы предпочел решение, используя только стандартные элементы управления и параметры. Я подозреваю, что решение может также мешать прокрутке, но я могу жить с этим.
EDIT: В частности, указанное отставание - это время, когда вы нажимаете палец на кнопку и удерживаете ее там, пока кнопка не переключится в нажатое состояние. Обработчик onClick вызывается, когда вы снова удаляете палец.
В некоторых ответах предлагалось переместить основную часть обработчика onClick в поток. Это не проблема. Чтобы сделать это вдвойне, я удалил все обработчики кликов, и крошечное отставание все еще существует.
Ответы
Ответ 1
Я вникнул в исходный код Android, чтобы узнать, что происходит.
Оказывается, что класс android.view.View(из которого вызывается Button) переходит в состояние "ПРЕДВАРИТЕЛЬНОЕ" перед переходом в состояние PRESSED:
android.view.View:
1529 /**
1530 * Indicates a prepressed state;
1531 * the short time between ACTION_DOWN and recognizing
1532 * a 'real' press. Prepressed is used to recognize quick taps
1533 * even when they are shorter than ViewConfiguration.getTapTimeout().
1534 *
1535 * @hide
1536 */
1537 private static final int PREPRESSED = 0x02000000;
android.view.ViewConfiguration.getTapTimeout() составляет 115 мс на моем Nexus One, что намного длиннее моей оценки.
android.view.ViewConfiguration:
67 /**
68 * Defines the duration in milliseconds we will wait to see if a touch event
69 * is a tap or a scroll. If the user does not move within this interval, it is
70 * considered to be a tap.
71 */
72 private static final int TAP_TIMEOUT = 115;
В любом случае, из рассмотрения View.onTouchEvent не похоже, что есть способ избежать этого состояния PREPRESSED с помощью любой стандартной опции. Это настоящий позор.
Хорошей новостью является то, что я теперь подтвердил, что способ избежать этого отставания заключается в подклассе и переопределении onTouchEvent.
Спасибо за обсуждение и ответы.
Ответ 2
Кажется, это исправлено:
public boolean onTouchEvent (MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) setPressed(true);
return super.onTouchEvent(event);
}
Все еще не идеально, но лучше.
Ответ 3
Ну... Я обычно расширяю класс Button и переопределяю метод onTouchEvent
public boolean onTouchEvent (MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
setPressed(true);
}
return super.onTouchEvent(event);
}
Ответ 4
Итак, что в основном происходит в любом приложении Android, так это то, что GUI запускается в основном потоке. Если вы столкнулись с другими тяжелыми вещами в том же потоке, как связь, видео, петли и т.д., Эти действия, безусловно, замедлят ваш графический интерфейс.
Это случилось с моим приложением в прошлом, затем я переместил все остальные процессы в отдельный поток каждый, и графический интерфейс стал действительно отзывчивым в режиме реального времени.